[interp] Add some error handling to the interpreter
[mono.git] / mono / mini / interp / transform.c
1 /**
2  * \file
3  * transform CIL into different opcodes for more
4  * efficient interpretation
5  *
6  * Written by Bernie Solomon (bernard@ugsolutions.com)
7  * Copyright (c) 2004.
8  */
9
10 #include <string.h>
11 #include <mono/metadata/appdomain.h>
12 #include <mono/metadata/debug-helpers.h>
13 #include <mono/metadata/exception.h>
14 #include <mono/metadata/mono-endian.h>
15 #include <mono/metadata/marshal.h>
16 #include <mono/metadata/profiler-private.h>
17 #include <mono/metadata/tabledefs.h>
18 #include <mono/metadata/seq-points-data.h>
19
20 #include <mono/mini/mini.h>
21
22 #include "mintops.h"
23 #include "interp-internals.h"
24 #include "interp.h"
25
26 // TODO: export from marshal.c
27 MonoDelegate* mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn);
28
29 #define DEBUG 0
30
31 typedef struct
32 {
33         MonoClass *klass;
34         unsigned char type;
35         unsigned char flags;
36 } StackInfo;
37
38 typedef struct {
39         guint8 *ip;
40         GSList *preds;
41         GSList *seq_points;
42         SeqPoint *last_seq_point;
43
44         // This will hold a list of last sequence points of incoming basic blocks
45         SeqPoint **pred_seq_points;
46         guint num_pred_seq_points;
47 } InterpBasicBlock;
48
49 typedef enum {
50         RELOC_SHORT_BRANCH,
51         RELOC_LONG_BRANCH,
52         RELOC_SWITCH
53 } RelocType;
54
55 typedef struct {
56         RelocType type;
57         /* In the interpreter IR */
58         int offset;
59         /* In the IL code */
60         int target;
61 } Reloc;
62
63 typedef struct
64 {
65         MonoMethod *method;
66         MonoMethodHeader *header;
67         InterpMethod *rtm;
68         const unsigned char *il_code;
69         const unsigned char *ip;
70         const unsigned char *last_ip;
71         const unsigned char *in_start;
72         int code_size;
73         int *in_offsets;
74         StackInfo **stack_state;
75         int *stack_height;
76         int *vt_stack_size;
77         unsigned char *is_bb_start;
78         unsigned short *new_code;
79         unsigned short *new_code_end;
80         unsigned short *new_ip;
81         unsigned short *last_new_ip;
82         unsigned int max_code_size;
83         StackInfo *stack;
84         StackInfo *sp;
85         unsigned int max_stack_height;
86         unsigned int vt_sp;
87         unsigned int max_vt_sp;
88         int n_data_items;
89         int max_data_items;
90         void **data_items;
91         GHashTable *data_hash;
92         int *clause_indexes;
93         gboolean gen_sdb_seq_points;
94         GPtrArray *seq_points;
95         InterpBasicBlock **offset_to_bb;
96         InterpBasicBlock *entry_bb;
97         MonoMemPool     *mempool;
98         GList *basic_blocks;
99         GPtrArray *relocs;
100         gboolean verbose_level;
101 } TransformData;
102
103 #define MINT_TYPE_I1 0
104 #define MINT_TYPE_U1 1
105 #define MINT_TYPE_I2 2
106 #define MINT_TYPE_U2 3
107 #define MINT_TYPE_I4 4
108 #define MINT_TYPE_I8 5
109 #define MINT_TYPE_R4 6
110 #define MINT_TYPE_R8 7
111 #define MINT_TYPE_O  8
112 #define MINT_TYPE_P  9
113 #define MINT_TYPE_VT 10
114
115 #define STACK_TYPE_I4 0
116 #define STACK_TYPE_I8 1
117 #define STACK_TYPE_R8 2
118 #define STACK_TYPE_O  3
119 #define STACK_TYPE_VT 4
120 #define STACK_TYPE_MP 5
121 #define STACK_TYPE_F  6
122
123 static const char *stack_type_string [] = { "I4", "I8", "R8", "O ", "VT", "MP", "F " };
124
125 #if SIZEOF_VOID_P == 8
126 #define STACK_TYPE_I STACK_TYPE_I8
127 #else
128 #define STACK_TYPE_I STACK_TYPE_I4
129 #endif
130
131 static int stack_type [] = {
132         STACK_TYPE_I4, /*I1*/
133         STACK_TYPE_I4, /*U1*/
134         STACK_TYPE_I4, /*I2*/
135         STACK_TYPE_I4, /*U2*/
136         STACK_TYPE_I4, /*I4*/
137         STACK_TYPE_I8, /*I8*/
138         STACK_TYPE_R8, /*R4*/
139         STACK_TYPE_R8, /*R8*/
140         STACK_TYPE_O,  /*O*/
141         STACK_TYPE_MP, /*P*/
142         STACK_TYPE_VT
143 };
144
145 #if SIZEOF_VOID_P == 8
146 #define MINT_NEG_P MINT_NEG_I8
147 #define MINT_NOT_P MINT_NOT_I8
148
149 #define MINT_NEG_FP MINT_NEG_R8
150
151 #define MINT_ADD_P MINT_ADD_I8
152 #define MINT_SUB_P MINT_SUB_I8
153 #define MINT_MUL_P MINT_MUL_I8
154 #define MINT_DIV_P MINT_DIV_I8
155 #define MINT_DIV_UN_P MINT_DIV_UN_I8
156 #define MINT_REM_P MINT_REM_I8
157 #define MINT_REM_UN_P MINT_REM_UN_I8
158 #define MINT_AND_P MINT_AND_I8
159 #define MINT_OR_P MINT_OR_I8
160 #define MINT_XOR_P MINT_XOR_I8
161 #define MINT_SHL_P MINT_SHL_I8
162 #define MINT_SHR_P MINT_SHR_I8
163 #define MINT_SHR_UN_P MINT_SHR_UN_I8
164
165 #define MINT_CEQ_P MINT_CEQ_I8
166 #define MINT_CNE_P MINT_CNE_I8
167 #define MINT_CLT_P MINT_CLT_I8
168 #define MINT_CLT_UN_P MINT_CLT_UN_I8
169 #define MINT_CGT_P MINT_CGT_I8
170 #define MINT_CGT_UN_P MINT_CGT_UN_I8
171 #define MINT_CLE_P MINT_CLE_I8
172 #define MINT_CLE_UN_P MINT_CLE_UN_I8
173 #define MINT_CGE_P MINT_CGE_I8
174 #define MINT_CGE_UN_P MINT_CGE_UN_I8
175
176 #define MINT_ADD_FP MINT_ADD_R8
177 #define MINT_SUB_FP MINT_SUB_R8
178 #define MINT_MUL_FP MINT_MUL_R8
179 #define MINT_DIV_FP MINT_DIV_R8
180 #define MINT_REM_FP MINT_REM_R8
181
182 #define MINT_CNE_FP MINT_CNE_R8
183 #define MINT_CEQ_FP MINT_CEQ_R8
184 #define MINT_CGT_FP MINT_CGT_R8
185 #define MINT_CGE_FP MINT_CGE_R8
186 #define MINT_CLT_FP MINT_CLT_R8
187 #define MINT_CLE_FP MINT_CLE_R8
188
189 #else
190
191 #define MINT_NEG_P MINT_NEG_I4
192 #define MINT_NOT_P MINT_NOT_I4
193
194 #define MINT_NEG_FP MINT_NEG_R8
195
196 #define MINT_ADD_P MINT_ADD_I4
197 #define MINT_SUB_P MINT_SUB_I4
198 #define MINT_MUL_P MINT_MUL_I4
199 #define MINT_DIV_P MINT_DIV_I4
200 #define MINT_DIV_UN_P MINT_DIV_UN_I4
201 #define MINT_REM_P MINT_REM_I4
202 #define MINT_REM_UN_P MINT_REM_UN_I4
203 #define MINT_AND_P MINT_AND_I4
204 #define MINT_OR_P MINT_OR_I4
205 #define MINT_XOR_P MINT_XOR_I4
206 #define MINT_SHL_P MINT_SHL_I4
207 #define MINT_SHR_P MINT_SHR_I4
208 #define MINT_SHR_UN_P MINT_SHR_UN_I4
209
210 #define MINT_CEQ_P MINT_CEQ_I4
211 #define MINT_CNE_P MINT_CNE_I4
212 #define MINT_CLT_P MINT_CLT_I4
213 #define MINT_CLT_UN_P MINT_CLT_UN_I4
214 #define MINT_CGT_P MINT_CGT_I4
215 #define MINT_CGT_UN_P MINT_CGT_UN_I4
216 #define MINT_CLE_P MINT_CLE_I4
217 #define MINT_CLE_UN_P MINT_CLE_UN_I4
218 #define MINT_CGE_P MINT_CGE_I4
219 #define MINT_CGE_UN_P MINT_CGE_UN_I4
220
221 #define MINT_ADD_FP MINT_ADD_R8
222 #define MINT_SUB_FP MINT_SUB_R8
223 #define MINT_MUL_FP MINT_MUL_R8
224 #define MINT_DIV_FP MINT_DIV_R8
225 #define MINT_REM_FP MINT_REM_R8
226
227 #define MINT_CNE_FP MINT_CNE_R8
228 #define MINT_CEQ_FP MINT_CEQ_R8
229 #define MINT_CGT_FP MINT_CGT_R8
230 #define MINT_CGE_FP MINT_CGE_R8
231 #define MINT_CLT_FP MINT_CLT_R8
232 #define MINT_CLE_FP MINT_CLE_R8
233
234 #endif
235
236 typedef struct {
237         const gchar *op_name;
238         guint16 insn [3];
239 } MagicIntrinsic;
240
241 // static const MagicIntrinsic int_binop[] = {
242
243 static const MagicIntrinsic int_unnop[] = {
244         { "op_UnaryPlus", {MINT_NOP, MINT_NOP, MINT_NOP}},
245         { "op_UnaryNegation", {MINT_NEG_P, MINT_NEG_P, MINT_NEG_FP}},
246         { "op_OnesComplement", {MINT_NOT_P, MINT_NOT_P, MINT_NIY}}
247 };
248
249 static const MagicIntrinsic int_binop[] = {
250         { "op_Addition", {MINT_ADD_P, MINT_ADD_P, MINT_ADD_FP}},
251         { "op_Subtraction", {MINT_SUB_P, MINT_SUB_P, MINT_SUB_FP}},
252         { "op_Multiply", {MINT_MUL_P, MINT_MUL_P, MINT_MUL_FP}},
253         { "op_Division", {MINT_DIV_P, MINT_DIV_UN_P, MINT_DIV_FP}},
254         { "op_Modulus", {MINT_REM_P, MINT_REM_UN_P, MINT_REM_FP}},
255         { "op_BitwiseAnd", {MINT_AND_P, MINT_AND_P, MINT_NIY}},
256         { "op_BitwiseOr", {MINT_OR_P, MINT_OR_P, MINT_NIY}},
257         { "op_ExclusiveOr", {MINT_XOR_P, MINT_XOR_P, MINT_NIY}},
258         { "op_LeftShift", {MINT_SHL_P, MINT_SHL_P, MINT_NIY}},
259         { "op_RightShift", {MINT_SHR_P, MINT_SHR_UN_P, MINT_NIY}},
260 };
261
262 static const MagicIntrinsic int_cmpop[] = {
263         { "op_Inequality", {MINT_CNE_P, MINT_CNE_P, MINT_CNE_FP}},
264         { "op_Equality", {MINT_CEQ_P, MINT_CEQ_P, MINT_CEQ_FP}},
265         { "op_GreaterThan", {MINT_CGT_P, MINT_CGT_UN_P, MINT_CGT_FP}},
266         { "op_GreaterThanOrEqual", {MINT_CGE_P, MINT_CGE_UN_P, MINT_CGE_FP}},
267         { "op_LessThan", {MINT_CLT_P, MINT_CLT_UN_P, MINT_CLT_FP}},
268         { "op_LessThanOrEqual", {MINT_CLE_P, MINT_CLE_UN_P, MINT_CLE_FP}}
269 };
270
271 static void
272 grow_code (TransformData *td)
273 {
274         unsigned int old_ip_offset = td->new_ip - td->new_code;
275         unsigned int old_last_ip_offset = td->last_new_ip - td->new_code;
276         g_assert (old_ip_offset <= td->max_code_size);
277         td->new_code = g_realloc (td->new_code, (td->max_code_size *= 2) * sizeof (td->new_code [0]));
278         td->new_code_end = td->new_code + td->max_code_size;
279         td->new_ip = td->new_code + old_ip_offset;
280         td->last_new_ip = td->new_code + old_last_ip_offset;
281 }
282
283 #define ENSURE_CODE(td, n) \
284         do { \
285                 if ((td)->new_ip + (n) > (td)->new_code_end) \
286                         grow_code (td); \
287         } while (0)
288
289 #define ADD_CODE(td, n) \
290         do { \
291                 if ((td)->new_ip == (td)->new_code_end) \
292                         grow_code (td); \
293                 *(td)->new_ip++ = (n); \
294         } while (0)
295
296 #define CHECK_STACK(td, n) \
297         do { \
298                 int stack_size = (td)->sp - (td)->stack; \
299                 if (stack_size < (n)) \
300                         g_warning ("%s.%s: not enough values (%d < %d) on stack at %04x", \
301                                 (td)->method->klass->name, (td)->method->name, \
302                                 stack_size, n, (td)->ip - (td)->il_code); \
303         } while (0)
304
305 #define ENSURE_I4(td, sp_off) \
306         do { \
307                 if ((td)->sp [-sp_off].type == STACK_TYPE_I8) \
308                         ADD_CODE(td, sp_off == 1 ? MINT_CONV_I4_I8 : MINT_CONV_I4_I8_SP); \
309         } while (0)
310
311 static void 
312 handle_branch (TransformData *td, int short_op, int long_op, int offset)
313 {
314         int shorten_branch = 0;
315         int target = td->ip + offset - td->il_code;
316         if (target < 0 || target >= td->code_size)
317                 g_assert_not_reached ();
318         if (offset > 0 && td->stack_height [target] < 0) {
319                 td->stack_height [target] = td->sp - td->stack;
320                 if (td->stack_height [target] > 0)
321                         td->stack_state [target] = g_memdup (td->stack, td->stack_height [target] * sizeof (td->stack [0]));
322                 td->vt_stack_size [target] = td->vt_sp;
323         }
324         if (offset < 0) {
325                 offset = td->in_offsets [target] - (td->new_ip - td->new_code);
326                 if (offset >= -32768) {
327                         shorten_branch = 1;
328                 }
329         } else {
330                 if (td->header->code_size <= 25000) /* FIX to be precise somehow? */
331                         shorten_branch = 1;
332
333                 Reloc *reloc = mono_mempool_alloc0 (td->mempool, sizeof (Reloc));
334                 if (shorten_branch) {
335                         offset = 0xffff;
336                         reloc->type = RELOC_SHORT_BRANCH;
337                 } else {
338                         offset = 0xdeadbeef;
339                         reloc->type = RELOC_LONG_BRANCH;
340                 }
341                 reloc->offset = td->new_ip - td->new_code;
342                 reloc->target = target;
343                 g_ptr_array_add (td->relocs, reloc);
344         }
345         if (shorten_branch) {
346                 ADD_CODE(td, short_op);
347                 ADD_CODE(td, offset);
348         } else {
349                 ADD_CODE(td, long_op);
350                 ADD_CODE(td, * (unsigned short *)(&offset));
351                 ADD_CODE(td, * ((unsigned short *)&offset + 1));
352         }
353 }
354
355 static void 
356 one_arg_branch(TransformData *td, int mint_op, int offset) 
357 {
358         int type = td->sp [-1].type == STACK_TYPE_O || td->sp [-1].type == STACK_TYPE_MP ? STACK_TYPE_I : td->sp [-1].type;
359         int long_op = mint_op + type - STACK_TYPE_I4;
360         int short_op = long_op + MINT_BRFALSE_I4_S - MINT_BRFALSE_I4;
361         CHECK_STACK(td, 1);
362         --td->sp;
363         handle_branch (td, short_op, long_op, offset);
364 }
365
366 static void 
367 two_arg_branch(TransformData *td, int mint_op, int offset) 
368 {
369         int type1 = td->sp [-1].type == STACK_TYPE_O || td->sp [-1].type == STACK_TYPE_MP ? STACK_TYPE_I : td->sp [-1].type;
370         int type2 = td->sp [-2].type == STACK_TYPE_O || td->sp [-2].type == STACK_TYPE_MP ? STACK_TYPE_I : td->sp [-2].type;
371         int long_op = mint_op + type1 - STACK_TYPE_I4;
372         int short_op = long_op + MINT_BEQ_I4_S - MINT_BEQ_I4;
373         CHECK_STACK(td, 2);
374         if (type1 == STACK_TYPE_I4 && type2 == STACK_TYPE_I8) {
375                 ADD_CODE(td, MINT_CONV_I8_I4);
376                 td->in_offsets [td->ip - td->il_code]++;
377         } else if (type1 == STACK_TYPE_I8 && type2 == STACK_TYPE_I4) {
378                 ADD_CODE(td, MINT_CONV_I8_I4_SP);
379                 td->in_offsets [td->ip - td->il_code]++;
380         } else if (type1 != type2) {
381                 g_warning("%s.%s: branch type mismatch %d %d", 
382                         td->method->klass->name, td->method->name, 
383                         td->sp [-1].type, td->sp [-2].type);
384         }
385         td->sp -= 2;
386         handle_branch (td, short_op, long_op, offset);
387 }
388
389 static void
390 unary_arith_op(TransformData *td, int mint_op)
391 {
392         int op = mint_op + td->sp [-1].type - STACK_TYPE_I4;
393         CHECK_STACK(td, 1);
394         ADD_CODE(td, op);
395 }
396
397 static void
398 binary_arith_op(TransformData *td, int mint_op)
399 {
400         int type1 = td->sp [-2].type;
401         int type2 = td->sp [-1].type;
402         int op;
403 #if SIZEOF_VOID_P == 8
404         if ((type1 == STACK_TYPE_MP || type1 == STACK_TYPE_I8) && type2 == STACK_TYPE_I4) {
405                 ADD_CODE(td, MINT_CONV_I8_I4);
406                 type2 = STACK_TYPE_I8;
407         }
408         if (type1 == STACK_TYPE_I4 && (type2 == STACK_TYPE_MP || type2 == STACK_TYPE_I8)) {
409                 ADD_CODE(td, MINT_CONV_I8_I4_SP);
410                 type1 = STACK_TYPE_I8;
411                 td->sp [-2].type = STACK_TYPE_I8;
412         }
413 #endif
414         if (type1 == STACK_TYPE_MP)
415                 type1 = STACK_TYPE_I;
416         if (type2 == STACK_TYPE_MP)
417                 type2 = STACK_TYPE_I;
418         if (type1 != type2) {
419                 g_warning("%s.%s: %04x arith type mismatch %s %d %d", 
420                         td->method->klass->name, td->method->name, 
421                         td->ip - td->il_code, mono_interp_opname[mint_op], type1, type2);
422         }
423         op = mint_op + type1 - STACK_TYPE_I4;
424         CHECK_STACK(td, 2);
425         ADD_CODE(td, op);
426         --td->sp;
427 }
428
429 static void
430 shift_op(TransformData *td, int mint_op)
431 {
432         int op = mint_op + td->sp [-2].type - STACK_TYPE_I4;
433         CHECK_STACK(td, 2);
434         if (td->sp [-1].type != STACK_TYPE_I4) {
435                 g_warning("%s.%s: shift type mismatch %d", 
436                         td->method->klass->name, td->method->name,
437                         td->sp [-2].type);
438         }
439         ADD_CODE(td, op);
440         --td->sp;
441 }
442
443 static int 
444 mint_type(MonoType *type_)
445 {
446         MonoType *type = mini_native_type_replace_type (type_);
447         if (type->byref)
448                 return MINT_TYPE_P;
449 enum_type:
450         switch (type->type) {
451         case MONO_TYPE_I1:
452                 return MINT_TYPE_I1;
453         case MONO_TYPE_U1:
454         case MONO_TYPE_BOOLEAN:
455                 return MINT_TYPE_U1;
456         case MONO_TYPE_I2:
457                 return MINT_TYPE_I2;
458         case MONO_TYPE_U2:
459         case MONO_TYPE_CHAR:
460                 return MINT_TYPE_U2;
461         case MONO_TYPE_I4:
462         case MONO_TYPE_U4:
463                 return MINT_TYPE_I4;
464         case MONO_TYPE_I:
465         case MONO_TYPE_U:
466 #if SIZEOF_VOID_P == 4
467                 return MINT_TYPE_I4;
468 #else
469                 return MINT_TYPE_I8;
470 #endif
471         case MONO_TYPE_PTR:
472                 return MINT_TYPE_P;
473         case MONO_TYPE_R4:
474                 return MINT_TYPE_R4;
475         case MONO_TYPE_I8:
476         case MONO_TYPE_U8:
477                 return MINT_TYPE_I8;
478         case MONO_TYPE_R8:
479                 return MINT_TYPE_R8;
480         case MONO_TYPE_STRING:
481         case MONO_TYPE_SZARRAY:
482         case MONO_TYPE_CLASS:
483         case MONO_TYPE_OBJECT:
484         case MONO_TYPE_ARRAY:
485                 return MINT_TYPE_O;
486         case MONO_TYPE_VALUETYPE:
487                 if (type->data.klass->enumtype) {
488                         type = mono_class_enum_basetype (type->data.klass);
489                         goto enum_type;
490                 } else
491                         return MINT_TYPE_VT;
492         case MONO_TYPE_TYPEDBYREF:
493                 return MINT_TYPE_VT;
494         case MONO_TYPE_GENERICINST:
495                 type = &type->data.generic_class->container_class->byval_arg;
496                 goto enum_type;
497         default:
498                 g_warning ("got type 0x%02x", type->type);
499                 g_assert_not_reached ();
500         }
501         return -1;
502 }
503
504 static int 
505 can_store (int stack_type, int var_type)
506 {
507         if (stack_type == STACK_TYPE_O || stack_type == STACK_TYPE_MP)
508                 stack_type = STACK_TYPE_I;
509         if (var_type == STACK_TYPE_O || var_type == STACK_TYPE_MP)
510                 var_type = STACK_TYPE_I;
511         return stack_type == var_type;
512 }
513
514 #define SET_SIMPLE_TYPE(s, ty) \
515         do { \
516                 (s)->type = (ty); \
517                 (s)->flags = 0; \
518                 (s)->klass = NULL; \
519         } while (0)
520
521 #define SET_TYPE(s, ty, k) \
522         do { \
523                 (s)->type = (ty); \
524                 (s)->flags = 0; \
525                 (s)->klass = k; \
526         } while (0)
527
528 #define PUSH_SIMPLE_TYPE(td, ty) \
529         do { \
530                 int sp_height; \
531                 (td)->sp++; \
532                 sp_height = (td)->sp - (td)->stack; \
533                 if (sp_height > (td)->max_stack_height) \
534                         (td)->max_stack_height = sp_height; \
535                 SET_SIMPLE_TYPE((td)->sp - 1, ty); \
536         } while (0)
537
538 #define PUSH_TYPE(td, ty, k) \
539         do { \
540                 int sp_height; \
541                 (td)->sp++; \
542                 sp_height = (td)->sp - (td)->stack; \
543                 if (sp_height > (td)->max_stack_height) \
544                         (td)->max_stack_height = sp_height; \
545                 SET_TYPE((td)->sp - 1, ty, k); \
546         } while (0)
547
548 #define PUSH_VT(td, size) \
549         do { \
550                 (td)->vt_sp += ((size) + 7) & ~7; \
551                 if ((td)->vt_sp > (td)->max_vt_sp) \
552                         (td)->max_vt_sp = (td)->vt_sp; \
553         } while (0)
554
555 #define POP_VT(td, size) \
556         do { \
557                 (td)->vt_sp -= ((size) + 7) & ~7; \
558         } while (0)
559
560 #if NO_UNALIGNED_ACCESS
561 #define WRITE32(td, v) \
562         do { \
563                 ENSURE_CODE(td, 2); \
564                 * (guint16 *)((td)->new_ip) = * (guint16 *)(v); \
565                 * ((guint16 *)((td)->new_ip) + 1) = * ((guint16 *)(v) + 1); \
566                 (td)->new_ip += 2; \
567         } while (0)
568
569 #define WRITE64(td, v) \
570         do { \
571                 ENSURE_CODE(td, 4); \
572                 * (guint16 *)((td)->new_ip) = * (guint16 *)(v); \
573                 * ((guint16 *)((td)->new_ip) + 1) = * ((guint16 *)(v) + 1); \
574                 * ((guint16 *)((td)->new_ip) + 2) = * ((guint16 *)(v) + 2); \
575                 * ((guint16 *)((td)->new_ip) + 3) = * ((guint16 *)(v) + 3); \
576                 (td)->new_ip += 4; \
577         } while (0)
578 #else
579 #define WRITE32(td, v) \
580         do { \
581                 ENSURE_CODE(td, 2); \
582                 * (guint32 *)((td)->new_ip) = * (guint32 *)(v); \
583                 (td)->new_ip += 2; \
584         } while (0)
585
586 #define WRITE64(td, v) \
587         do { \
588                 ENSURE_CODE(td, 4); \
589                 * (guint64 *)((td)->new_ip) = * (guint64 *)(v); \
590                 (td)->new_ip += 4; \
591         } while (0)
592
593 #endif
594
595 static void 
596 load_arg(TransformData *td, int n)
597 {
598         int mt;
599         MonoClass *klass = NULL;
600         MonoType *type;
601
602         gboolean hasthis = mono_method_signature (td->method)->hasthis;
603         if (hasthis && n == 0)
604                 type = &td->method->klass->byval_arg;
605         else
606                 type = mono_method_signature (td->method)->params [hasthis ? n - 1 : n];
607
608         mt = mint_type (type);
609         if (mt == MINT_TYPE_VT) {
610                 gint32 size;
611                 klass = mono_class_from_mono_type (type);
612                 if (mono_method_signature (td->method)->pinvoke)
613                         size = mono_class_native_size (klass, NULL);
614                 else
615                         size = mono_class_value_size (klass, NULL);
616
617                 if (hasthis && n == 0) {
618                         mt = MINT_TYPE_P;
619                         ADD_CODE (td, MINT_LDARG_P);
620                         ADD_CODE (td, td->rtm->arg_offsets [n]); /* FIX for large offset */
621                         klass = NULL;
622                 } else {
623                         PUSH_VT (td, size);
624                         ADD_CODE (td, MINT_LDARG_VT);
625                         ADD_CODE (td, td->rtm->arg_offsets [n]); /* FIX for large offset */
626                         WRITE32 (td, &size);
627                 }
628         } else {
629                 if (hasthis && n == 0) {
630                         mt = MINT_TYPE_P;
631                         ADD_CODE (td, MINT_LDARG_P);
632                         ADD_CODE (td, td->rtm->arg_offsets [n]); /* FIX for large offset */
633                         klass = NULL;
634                 } else {
635                         ADD_CODE(td, MINT_LDARG_I1 + (mt - MINT_TYPE_I1));
636                         ADD_CODE(td, td->rtm->arg_offsets [n]); /* FIX for large offset */
637                         if (mt == MINT_TYPE_O)
638                                 klass = mono_class_from_mono_type (type);
639                 }
640         }
641         PUSH_TYPE(td, stack_type[mt], klass);
642 }
643
644 static void 
645 store_arg(TransformData *td, int n)
646 {
647         int mt;
648         CHECK_STACK (td, 1);
649         MonoType *type;
650
651         gboolean hasthis = mono_method_signature (td->method)->hasthis;
652         if (hasthis && n == 0)
653                 type = &td->method->klass->byval_arg;
654         else
655                 type = mono_method_signature (td->method)->params [n - !!hasthis];
656
657         mt = mint_type (type);
658         if (mt == MINT_TYPE_VT) {
659                 gint32 size;
660                 MonoClass *klass = mono_class_from_mono_type (type);
661                 if (mono_method_signature (td->method)->pinvoke)
662                         size = mono_class_native_size (klass, NULL);
663                 else
664                         size = mono_class_value_size (klass, NULL);
665                 ADD_CODE(td, MINT_STARG_VT);
666                 ADD_CODE(td, td->rtm->arg_offsets [n]);
667                 WRITE32(td, &size);
668                 if (td->sp [-1].type == STACK_TYPE_VT)
669                         POP_VT(td, size);
670         } else {
671                 ADD_CODE(td, MINT_STARG_I1 + (mt - MINT_TYPE_I1));
672                 ADD_CODE(td, td->rtm->arg_offsets [n]);
673         }
674         --td->sp;
675 }
676
677 static void 
678 store_inarg(TransformData *td, int n)
679 {
680         MonoType *type;
681         gboolean hasthis = mono_method_signature (td->method)->hasthis;
682         if (hasthis && n == 0)
683                 type = &td->method->klass->byval_arg;
684         else
685                 type = mono_method_signature (td->method)->params [n - !!hasthis];
686
687         int mt = mint_type (type);
688         if (hasthis && n == 0) {
689                 ADD_CODE (td, MINT_STINARG_P);
690                 ADD_CODE (td, n);
691                 return;
692         }
693         if (mt == MINT_TYPE_VT) {
694                 MonoClass *klass = mono_class_from_mono_type (type);
695                 gint32 size;
696                 if (mono_method_signature (td->method)->pinvoke)
697                         size = mono_class_native_size (klass, NULL);
698                 else
699                         size = mono_class_value_size (klass, NULL);
700                 ADD_CODE(td, MINT_STINARG_VT);
701                 ADD_CODE(td, n);
702                 WRITE32(td, &size);
703         } else {
704                 ADD_CODE(td, MINT_STINARG_I1 + (mt - MINT_TYPE_I1));
705                 ADD_CODE(td, n);
706         }
707 }
708
709 static void 
710 load_local(TransformData *td, int n)
711 {
712         MonoType *type = td->header->locals [n];
713         int mt = mint_type (type);
714         int offset = td->rtm->local_offsets [n];
715         MonoClass *klass = NULL;
716         if (mt == MINT_TYPE_VT) {
717                 klass = mono_class_from_mono_type (type);
718                 gint32 size = mono_class_value_size (klass, NULL);
719                 PUSH_VT(td, size);
720                 ADD_CODE(td, MINT_LDLOC_VT);
721                 ADD_CODE(td, offset); /*FIX for large offset */
722                 WRITE32(td, &size);
723         } else {
724                 g_assert (mt < MINT_TYPE_VT);
725                 if (!td->gen_sdb_seq_points &&
726                         mt == MINT_TYPE_I4 && !td->is_bb_start [td->in_start - td->il_code] && td->last_new_ip != NULL &&
727                         td->last_new_ip [0] == MINT_STLOC_I4 && td->last_new_ip [1] == offset) {
728                         td->last_new_ip [0] = MINT_STLOC_NP_I4;
729                 } else if (!td->gen_sdb_seq_points &&
730                                    mt == MINT_TYPE_O && !td->is_bb_start [td->in_start - td->il_code] && td->last_new_ip != NULL &&
731                                    td->last_new_ip [0] == MINT_STLOC_O && td->last_new_ip [1] == offset) {
732                         td->last_new_ip [0] = MINT_STLOC_NP_O;
733                 } else {
734                         ADD_CODE(td, MINT_LDLOC_I1 + (mt - MINT_TYPE_I1));
735                         ADD_CODE(td, offset); /*FIX for large offset */
736                 }
737                 if (mt == MINT_TYPE_O)
738                         klass = mono_class_from_mono_type (type);
739         }
740         PUSH_TYPE(td, stack_type[mt], klass);
741 }
742
743 static void 
744 store_local(TransformData *td, int n)
745 {
746         MonoType *type = td->header->locals [n];
747         int mt = mint_type (type);
748         int offset = td->rtm->local_offsets [n];
749         CHECK_STACK (td, 1);
750 #if SIZEOF_VOID_P == 8
751         if (td->sp [-1].type == STACK_TYPE_I4 && stack_type [mt] == STACK_TYPE_I8) {
752                 ADD_CODE(td, MINT_CONV_I8_I4);
753                 td->sp [-1].type = STACK_TYPE_I8;
754         }
755 #endif
756         if (!can_store(td->sp [-1].type, stack_type [mt])) {
757                 g_warning("%s.%s: Store local stack type mismatch %d %d", 
758                         td->method->klass->name, td->method->name,
759                         stack_type [mt], td->sp [-1].type);
760         }
761         if (mt == MINT_TYPE_VT) {
762                 MonoClass *klass = mono_class_from_mono_type (type);
763                 gint32 size = mono_class_value_size (klass, NULL);
764                 ADD_CODE(td, MINT_STLOC_VT);
765                 ADD_CODE(td, offset); /*FIX for large offset */
766                 WRITE32(td, &size);
767                 if (td->sp [-1].type == STACK_TYPE_VT)
768                         POP_VT(td, size);
769         } else {
770                 g_assert (mt < MINT_TYPE_VT);
771                 ADD_CODE(td, MINT_STLOC_I1 + (mt - MINT_TYPE_I1));
772                 ADD_CODE(td, offset); /*FIX for large offset */
773         }
774         --td->sp;
775 }
776
777 #define SIMPLE_OP(td, op) \
778         do { \
779                 ADD_CODE(td, op); \
780                 ++td->ip; \
781         } while (0)
782
783 static guint16
784 get_data_item_index (TransformData *td, void *ptr)
785 {
786         gpointer p = g_hash_table_lookup (td->data_hash, ptr);
787         guint index;
788         if (p != NULL)
789                 return GPOINTER_TO_UINT (p) - 1;
790         if (td->max_data_items == td->n_data_items) {
791                 td->max_data_items = td->n_data_items == 0 ? 16 : 2 * td->max_data_items;
792                 td->data_items = g_realloc (td->data_items, td->max_data_items * sizeof(td->data_items [0]));
793         }
794         index = td->n_data_items;
795         td->data_items [index] = ptr;
796         ++td->n_data_items;
797         g_hash_table_insert (td->data_hash, ptr, GUINT_TO_POINTER (index + 1));
798         return index;
799 }
800
801 static gboolean
802 jit_call_supported (MonoMethod *method, MonoMethodSignature *sig)
803 {
804         GSList *l;
805
806         if (sig->param_count > 6)
807                 return FALSE;
808         if (sig->pinvoke)
809                 return FALSE;
810         if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
811                 return FALSE;
812         if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
813                 return FALSE;
814         if (method->is_inflated)
815                 return FALSE;
816         if (method->string_ctor)
817                 return FALSE;
818
819         for (l = jit_classes; l; l = l->next) {
820                 char *class_name = l->data;
821                 // FIXME: Namespaces
822                 if (!strcmp (method->klass->name, class_name))
823                         return TRUE;
824         }
825
826         //return TRUE;
827         return FALSE;
828 }
829
830 static inline gboolean
831 type_size (MonoType *type)
832 {
833         if (type->type == MONO_TYPE_I4 || type->type == MONO_TYPE_U4)
834                 return 4;
835         else if (type->type == MONO_TYPE_I8 || type->type == MONO_TYPE_U8)
836                 return 8;
837         else if (type->type == MONO_TYPE_R4 && !type->byref)
838                 return 4;
839         else if (type->type == MONO_TYPE_R8 && !type->byref)
840                 return 8;
841         return SIZEOF_VOID_P;
842 }
843
844 static int mono_class_get_magic_index (MonoClass *k)
845 {
846         if (mono_class_is_magic_int (k))
847                 return !strcmp ("nint", k->name) ? 0 : 1;
848
849         if (mono_class_is_magic_float (k))
850                 return 2;
851
852         return -1;
853 }
854
855
856 static void
857 interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target_method, MonoDomain *domain, MonoGenericContext *generic_context, unsigned char *is_bb_start, int body_start_offset, MonoClass *constrained_class, gboolean readonly)
858 {
859         MonoImage *image = method->klass->image;
860         MonoMethodSignature *csignature;
861         MonoError error;
862         int virtual = *td->ip == CEE_CALLVIRT;
863         int calli = *td->ip == CEE_CALLI || *td->ip == CEE_MONO_CALLI_EXTRA_ARG;
864         int i;
865         guint32 vt_stack_used = 0;
866         guint32 vt_res_size = 0;
867         int op = -1;
868         int native = 0;
869         int is_void = 0;
870
871         guint32 token = read32 (td->ip + 1);
872
873         if (target_method == NULL) {
874                 if (calli) {
875                         CHECK_STACK(td, 1);
876                         native = (method->wrapper_type != MONO_WRAPPER_DELEGATE_INVOKE && td->sp [-1].type == STACK_TYPE_I);
877                         --td->sp;
878                         if (method->wrapper_type != MONO_WRAPPER_NONE)
879                                 csignature = (MonoMethodSignature *)mono_method_get_wrapper_data (method, token);
880                         else
881                                 csignature = mono_metadata_parse_signature (image, token);
882
883                         if (generic_context) {
884                                 csignature = mono_inflate_generic_signature (csignature, generic_context, &error);
885                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
886                         }
887
888                         target_method = NULL;
889                 } else {
890                         if (method->wrapper_type == MONO_WRAPPER_NONE)
891                                 target_method = mono_get_method_full (image, token, NULL, generic_context);
892                         else
893                                 target_method = (MonoMethod *)mono_method_get_wrapper_data (method, token);
894                         csignature = mono_method_signature (target_method);
895
896                         if (generic_context) {
897                                 csignature = mono_inflate_generic_signature (csignature, generic_context, &error);
898                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
899                                 target_method = mono_class_inflate_generic_method_checked (target_method, generic_context, &error);
900                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
901                         }
902                 }
903         } else {
904                 csignature = mono_method_signature (target_method);
905         }
906
907         if (target_method && target_method->string_ctor) {
908                 /* Create the real signature */
909                 MonoMethodSignature *ctor_sig = mono_metadata_signature_dup_mempool (td->mempool, csignature);
910                 ctor_sig->ret = &mono_defaults.string_class->byval_arg;
911
912                 csignature = ctor_sig;
913         }
914
915         /* Intrinsics */
916         if (target_method) {
917                 const char *tm = target_method->name;
918                 int type_index = mono_class_get_magic_index (target_method->klass);
919
920                 if (target_method->klass == mono_defaults.string_class) {
921                         if (tm [0] == 'g') {
922                                 if (strcmp (tm, "get_Chars") == 0)
923                                         op = MINT_GETCHR;
924                                 else if (strcmp (tm, "get_Length") == 0)
925                                         op = MINT_STRLEN;
926                         }
927                 } else if (type_index >= 0) {
928                         MonoClass *magic_class = target_method->klass;
929
930                         const int mt = mint_type (&magic_class->byval_arg);
931                         if (!strcmp (".ctor", tm)) {
932                                 MonoType *arg = csignature->params [0];
933                                 /* depending on SIZEOF_VOID_P and the type of the value passed to the .ctor we either have to CONV it, or do nothing */
934                                 int arg_size = type_size (arg);
935
936                                 if (arg_size > SIZEOF_VOID_P) { // 8 -> 4
937                                         switch (type_index) {
938                                         case 0: case 1:
939                                                 ADD_CODE (td, MINT_CONV_I8_I4);
940                                                 break;
941                                         case 2:
942                                                 // ADD_CODE (td, MINT_CONV_R8_R4);
943                                                 break;
944                                         }
945                                 }
946
947                                 if (arg_size < SIZEOF_VOID_P) { // 4 -> 8
948                                         switch (type_index) {
949                                         case 0: case 1:
950                                                 ADD_CODE (td, MINT_CONV_I4_I8);
951                                                 break;
952                                         case 2:
953                                                 ADD_CODE (td, MINT_CONV_R4_R8);
954                                                 break;
955                                         }
956                                 }
957
958                                 switch (type_index) {
959                                 case 0: case 1:
960 #if SIZEOF_VOID_P == 4
961                                         ADD_CODE (td, MINT_STIND_I4);
962 #else
963                                         ADD_CODE (td, MINT_STIND_I8);
964 #endif
965                                         break;
966                                 case 2:
967 #if SIZEOF_VOID_P == 4
968                                         ADD_CODE (td, MINT_STIND_R4);
969 #else
970                                         ADD_CODE (td, MINT_STIND_R8);
971 #endif
972                                         break;
973                                 }
974
975                                 td->sp -= 2;
976                                 td->ip += 5;
977                                 return;
978                         } else if (!strcmp ("op_Implicit", tm ) || !strcmp ("op_Explicit", tm)) {
979                                 int arg_size = type_size (csignature->params [0]);
980                                 if (arg_size > SIZEOF_VOID_P) { // 8 -> 4
981                                         switch (type_index) {
982                                         case 0: case 1:
983                                                 ADD_CODE (td, MINT_CONV_I8_I4);
984                                                 break;
985                                         case 2:
986                                                 // ADD_CODE (td, MINT_CONV_R4_R8);
987                                                 break;
988                                         }
989                                 }
990
991                                 if (arg_size < SIZEOF_VOID_P) { // 4 -> 8
992                                         switch (type_index) {
993                                         case 0: case 1:
994                                                 ADD_CODE (td, MINT_CONV_I4_I8);
995                                                 break;
996                                         case 2:
997                                                 ADD_CODE (td, MINT_CONV_R4_R8);
998                                                 break;
999                                         }
1000                                 }
1001
1002                                 SET_TYPE (td->sp - 1, stack_type [mt], magic_class);
1003                                 td->ip += 5;
1004                                 return;
1005                         } else if (!strcmp (".cctor", tm)) {
1006                                 /* white list */
1007                                 goto no_intrinsic;
1008                         } else if (!strcmp ("Parse", tm)) {
1009                                 /* white list */
1010                                 goto no_intrinsic;
1011                         }
1012
1013                         for (i = 0; i < sizeof (int_unnop) / sizeof  (MagicIntrinsic); ++i) {
1014                                 if (!strcmp (int_unnop [i].op_name, tm)) {
1015                                         ADD_CODE (td, int_unnop [i].insn [type_index]);
1016                                         SET_TYPE (td->sp - 1, stack_type [mt], magic_class);
1017                                         td->ip += 5;
1018                                         return;
1019                                 }
1020                         }
1021
1022                         for (i = 0; i < sizeof (int_binop) / sizeof  (MagicIntrinsic); ++i) {
1023                                 if (!strcmp (int_binop [i].op_name, tm)) {
1024                                         ADD_CODE (td, int_binop [i].insn [type_index]);
1025                                         td->sp -= 1;
1026                                         SET_TYPE (td->sp - 1, stack_type [mt], magic_class);
1027                                         td->ip += 5;
1028                                         return;
1029                                 }
1030                         }
1031
1032                         for (i = 0; i < sizeof (int_cmpop) / sizeof  (MagicIntrinsic); ++i) {
1033                                 if (!strcmp (int_cmpop [i].op_name, tm)) {
1034                                         MonoClass *k = mono_defaults.boolean_class;
1035                                         ADD_CODE (td, int_cmpop [i].insn [type_index]);
1036                                         td->sp -= 1;
1037                                         SET_TYPE (td->sp - 1, stack_type [mint_type (&k->byval_arg)], k);
1038                                         td->ip += 5;
1039                                         return;
1040                                 }
1041                         }
1042
1043                         g_error ("TODO: %s", tm);
1044                 } else if (mono_class_is_subclass_of (target_method->klass, mono_defaults.array_class, FALSE)) {
1045                         if (!strcmp (tm, "get_Rank")) {
1046                                 op = MINT_ARRAY_RANK;
1047                         } else if (!strcmp (tm, "get_Length")) {
1048                                 op = MINT_LDLEN;
1049                         } else if (!strcmp (tm, "Address")) {
1050                                 op = readonly ? MINT_LDELEMA : MINT_LDELEMA_TC;
1051                         }
1052                 } else if (target_method->klass->image == mono_defaults.corlib &&
1053                                    (strcmp (target_method->klass->name_space, "System.Diagnostics") == 0) &&
1054                                    (strcmp (target_method->klass->name, "Debugger") == 0)) {
1055                         if (!strcmp (tm, "Break") && csignature->param_count == 0) {
1056                                 if (mini_should_insert_breakpoint (method))
1057                                         op = MINT_BREAK;
1058                         }
1059                 }
1060         }
1061 no_intrinsic:
1062
1063         if (constrained_class) {
1064                 if (constrained_class->enumtype && !strcmp (target_method->name, "GetHashCode")) {
1065                         /* Use the corresponding method from the base type to avoid boxing */
1066                         MonoType *base_type = mono_class_enum_basetype (constrained_class);
1067                         g_assert (base_type);
1068                         constrained_class = mono_class_from_mono_type (base_type);
1069                         target_method = mono_class_get_method_from_name (constrained_class, target_method->name, 0);
1070                         g_assert (target_method);
1071                 }
1072         }
1073
1074         if (constrained_class) {
1075                 mono_class_setup_vtable (constrained_class);
1076 #if DEBUG_INTERP
1077                 g_print ("CONSTRAINED.CALLVIRT: %s::%s.  %s (%p) ->\n", target_method->klass->name, target_method->name, mono_signature_full_name (target_method->signature), target_method);
1078 #endif
1079                 target_method = mono_get_method_constrained_with_method (image, target_method, constrained_class, generic_context, &error);
1080 #if DEBUG_INTERP
1081                 g_print ("                    : %s::%s.  %s (%p)\n", target_method->klass->name, target_method->name, mono_signature_full_name (target_method->signature), target_method);
1082 #endif
1083                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
1084                 mono_class_setup_vtable (target_method->klass);
1085
1086                 if (constrained_class->valuetype && (target_method->klass == mono_defaults.object_class || target_method->klass == mono_defaults.enum_class->parent || target_method->klass == mono_defaults.enum_class)) {
1087                         if (target_method->klass == mono_defaults.enum_class && (td->sp - csignature->param_count - 1)->type == STACK_TYPE_MP) {
1088                                 /* managed pointer on the stack, we need to deref that puppy */
1089                                 ADD_CODE (td, MINT_LDIND_I);
1090                                 ADD_CODE (td, csignature->param_count);
1091                         }
1092                         ADD_CODE (td, MINT_BOX);
1093                         ADD_CODE (td, get_data_item_index (td, constrained_class));
1094                         ADD_CODE (td, csignature->param_count);
1095                 } else if (!constrained_class->valuetype) {
1096                         /* managed pointer on the stack, we need to deref that puppy */
1097                         ADD_CODE (td, MINT_LDIND_I);
1098                         ADD_CODE (td, csignature->param_count);
1099                 } else {
1100                         if (target_method->klass->valuetype) {
1101                                 /* Own method */
1102                         } else {
1103                                 /* Interface method */
1104                                 int ioffset, slot;
1105
1106                                 mono_class_setup_vtable (constrained_class);
1107                                 ioffset = mono_class_interface_offset (constrained_class, target_method->klass);
1108                                 if (ioffset == -1)
1109                                         g_error ("type load error: constrained_class");
1110                                 slot = mono_method_get_vtable_slot (target_method);
1111                                 if (slot == -1)
1112                                         g_error ("type load error: target_method->klass");
1113                                 target_method = constrained_class->vtable [ioffset + slot];
1114
1115                                 if (target_method->klass == mono_defaults.enum_class) {
1116                                         if ((td->sp - csignature->param_count - 1)->type == STACK_TYPE_MP) {
1117                                                 /* managed pointer on the stack, we need to deref that puppy */
1118                                                 ADD_CODE (td, MINT_LDIND_I);
1119                                                 ADD_CODE (td, csignature->param_count);
1120                                         }
1121                                         ADD_CODE (td, MINT_BOX);
1122                                         ADD_CODE (td, get_data_item_index (td, constrained_class));
1123                                         ADD_CODE (td, csignature->param_count);
1124                                 }
1125                         }
1126                         virtual = FALSE;
1127                 }
1128         }
1129
1130         if (target_method)
1131                 mono_class_init (target_method->klass);
1132
1133         CHECK_STACK (td, csignature->param_count + csignature->hasthis);
1134         if (!calli && op == -1 && (!virtual || (target_method->flags & METHOD_ATTRIBUTE_VIRTUAL) == 0) &&
1135                 (target_method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) == 0 && 
1136                 (target_method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) == 0 &&
1137                 !(target_method->iflags & METHOD_IMPL_ATTRIBUTE_NOINLINING)) {
1138                 int called_inited = mono_class_vtable (domain, target_method->klass)->initialized;
1139                 MonoMethodHeader *mheader = mono_method_get_header (target_method);
1140
1141                 if (/*mono_metadata_signature_equal (method->signature, target_method->signature) */ method == target_method && *(td->ip + 5) == CEE_RET) {
1142                         int offset;
1143                         if (td->verbose_level)
1144                                 g_print ("Optimize tail call of %s.%s\n", target_method->klass->name, target_method->name);
1145
1146                         for (i = csignature->param_count - 1 + !!csignature->hasthis; i >= 0; --i)
1147                                 store_arg (td, i);
1148
1149                         ADD_CODE(td, MINT_BR_S);
1150                         offset = body_start_offset - ((td->new_ip - 1) - td->new_code);
1151                         ADD_CODE(td, offset);
1152                         if (!is_bb_start [td->ip + 5 - td->il_code])
1153                                 ++td->ip; /* gobble the CEE_RET if it isn't branched to */                              
1154                         td->ip += 5;
1155                         return;
1156                 } else {
1157                         /* mheader might not exist if this is a delegate invoc, etc */
1158                         if (mheader && *mheader->code == CEE_RET && called_inited) {
1159                                 if (td->verbose_level)
1160                                         g_print ("Inline (empty) call of %s.%s\n", target_method->klass->name, target_method->name);
1161                                 for (i = 0; i < csignature->param_count; i++) {
1162                                         ADD_CODE (td, MINT_POP); /*FIX: vt */
1163                                         ADD_CODE (td, 0);
1164                                 }
1165                                 if (csignature->hasthis) {
1166                                         if (virtual)
1167                                                 ADD_CODE(td, MINT_CKNULL);
1168                                         ADD_CODE (td, MINT_POP);
1169                                         ADD_CODE (td, 0);
1170                                 }
1171                                 td->sp -= csignature->param_count + csignature->hasthis;
1172                                 td->ip += 5;
1173                                 return;
1174                         }
1175                 }
1176         }
1177         if (method->wrapper_type == MONO_WRAPPER_NONE && target_method != NULL) {
1178                 if (target_method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
1179                         target_method = mono_marshal_get_native_wrapper (target_method, FALSE, FALSE);
1180                 if (!virtual && target_method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
1181                         target_method = mono_marshal_get_synchronized_wrapper (target_method);
1182         }
1183         g_assert (csignature->call_convention == MONO_CALL_DEFAULT || csignature->call_convention == MONO_CALL_C);
1184         td->sp -= csignature->param_count + !!csignature->hasthis;
1185         for (i = 0; i < csignature->param_count; ++i) {
1186                 if (td->sp [i + !!csignature->hasthis].type == STACK_TYPE_VT) {
1187                         gint32 size;
1188                         MonoClass *klass = mono_class_from_mono_type (csignature->params [i]);
1189                         if (csignature->pinvoke && method->wrapper_type != MONO_WRAPPER_NONE)
1190                                 size = mono_class_native_size (klass, NULL);
1191                         else
1192                                 size = mono_class_value_size (klass, NULL);
1193                         size = (size + 7) & ~7;
1194                         vt_stack_used += size;
1195                 }
1196         }
1197
1198         /* need to handle typedbyref ... */
1199         if (csignature->ret->type != MONO_TYPE_VOID) {
1200                 int mt = mint_type(csignature->ret);
1201                 MonoClass *klass = mono_class_from_mono_type (csignature->ret);
1202                 if (mt == MINT_TYPE_VT) {
1203                         if (csignature->pinvoke && method->wrapper_type != MONO_WRAPPER_NONE)
1204                                 vt_res_size = mono_class_native_size (klass, NULL);
1205                         else
1206                                 vt_res_size = mono_class_value_size (klass, NULL);
1207                         PUSH_VT(td, vt_res_size);
1208                 }
1209                 PUSH_TYPE(td, stack_type[mt], klass);
1210         } else
1211                 is_void = TRUE;
1212
1213         if (op >= 0) {
1214                 ADD_CODE (td, op);
1215 #if SIZEOF_VOID_P == 8
1216                 if (op == MINT_LDLEN)
1217                         ADD_CODE (td, MINT_CONV_I4_I8);
1218 #endif
1219                 if (op == MINT_LDELEMA || op == MINT_LDELEMA_TC) {
1220                         ADD_CODE (td, get_data_item_index (td, target_method->klass));
1221                         ADD_CODE (td, 1 + target_method->klass->rank);
1222                 }
1223         } else if (!calli && !virtual && jit_call_supported (target_method, csignature)) {
1224                 ADD_CODE(td, MINT_JIT_CALL);
1225                 ADD_CODE(td, get_data_item_index (td, (void *)mono_interp_get_imethod (domain, target_method, &error)));
1226                 mono_error_assert_ok (&error);
1227         } else {
1228                 if (calli)
1229                         ADD_CODE(td, native ? MINT_CALLI_NAT : MINT_CALLI);
1230                 else if (virtual)
1231                         ADD_CODE(td, is_void ? MINT_VCALLVIRT : MINT_CALLVIRT);
1232                 else
1233                         ADD_CODE(td, is_void ? MINT_VCALL : MINT_CALL);
1234
1235                 if (calli) {
1236                         ADD_CODE(td, get_data_item_index (td, (void *)csignature));
1237                 } else {
1238                         ADD_CODE(td, get_data_item_index (td, (void *)mono_interp_get_imethod (domain, target_method, &error)));
1239                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
1240                 }
1241         }
1242         td->ip += 5;
1243         if (vt_stack_used != 0 || vt_res_size != 0) {
1244                 ADD_CODE(td, MINT_VTRESULT);
1245                 ADD_CODE(td, vt_res_size);
1246                 WRITE32(td, &vt_stack_used);
1247                 td->vt_sp -= vt_stack_used;
1248         }
1249 }
1250
1251 static MonoClassField *
1252 interp_field_from_token (MonoMethod *method, guint32 token, MonoClass **klass, MonoGenericContext *generic_context)
1253 {
1254         MonoClassField *field = NULL;
1255         if (method->wrapper_type != MONO_WRAPPER_NONE) {
1256                 field = (MonoClassField *) mono_method_get_wrapper_data (method, token);
1257                 *klass = field->parent;
1258         } else {
1259                 MonoError error;
1260                 error_init (&error);
1261                 field = mono_field_from_token_checked (method->klass->image, token, klass, generic_context, &error);
1262                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
1263         }
1264         return field;
1265 }
1266
1267 static InterpBasicBlock*
1268 get_bb (TransformData *td, InterpBasicBlock *cbb, unsigned char *ip)
1269 {
1270         int offset = ip - td->il_code;
1271         InterpBasicBlock *bb = td->offset_to_bb [offset];
1272
1273         if (!bb) {
1274                 bb = mono_mempool_alloc0 (td->mempool, sizeof (InterpBasicBlock));
1275                 bb->ip = ip;
1276                 td->offset_to_bb [offset] = bb;
1277
1278                 td->basic_blocks = g_list_append_mempool (td->mempool, td->basic_blocks, bb);
1279         }
1280
1281         if (cbb)
1282                 bb->preds = g_slist_prepend_mempool (td->mempool, bb->preds, cbb);
1283         return bb;
1284 }
1285
1286 /*
1287  * get_basic_blocks:
1288  *
1289  *   Compute the set of IL level basic blocks.
1290  */
1291 static void
1292 get_basic_blocks (TransformData *td)
1293 {
1294         guint8 *start = (guint8*)td->il_code;
1295         guint8 *end = (guint8*)td->il_code + td->code_size;
1296         guint8 *ip = start;
1297         unsigned char *target;
1298         int i;
1299         guint cli_addr;
1300         const MonoOpcode *opcode;
1301         InterpBasicBlock *cbb;
1302
1303         td->offset_to_bb = mono_mempool_alloc0 (td->mempool, sizeof (InterpBasicBlock*) * (end - start + 1));
1304         td->entry_bb = cbb = get_bb (td, NULL, start);
1305
1306         while (ip < end) {
1307                 cli_addr = ip - start;
1308                 td->offset_to_bb [cli_addr] = cbb;
1309                 i = mono_opcode_value ((const guint8 **)&ip, end);
1310                 opcode = &mono_opcodes [i];
1311                 switch (opcode->argument) {
1312                 case MonoInlineNone:
1313                         ip++;
1314                         break;
1315                 case MonoInlineString:
1316                 case MonoInlineType:
1317                 case MonoInlineField:
1318                 case MonoInlineMethod:
1319                 case MonoInlineTok:
1320                 case MonoInlineSig:
1321                 case MonoShortInlineR:
1322                 case MonoInlineI:
1323                         ip += 5;
1324                         break;
1325                 case MonoInlineVar:
1326                         ip += 3;
1327                         break;
1328                 case MonoShortInlineVar:
1329                 case MonoShortInlineI:
1330                         ip += 2;
1331                         break;
1332                 case MonoShortInlineBrTarget:
1333                         target = start + cli_addr + 2 + (signed char)ip [1];
1334                         get_bb (td, cbb, target);
1335                         ip += 2;
1336                         cbb = get_bb (td, cbb, ip);
1337                         break;
1338                 case MonoInlineBrTarget:
1339                         target = start + cli_addr + 5 + (gint32)read32 (ip + 1);
1340                         get_bb (td, cbb, target);
1341                         ip += 5;
1342                         cbb = get_bb (td, cbb, ip);
1343                         break;
1344                 case MonoInlineSwitch: {
1345                         guint32 n = read32 (ip + 1);
1346                         guint32 j;
1347                         ip += 5;
1348                         cli_addr += 5 + 4 * n;
1349                         target = start + cli_addr;
1350                         get_bb (td, cbb, target);
1351
1352                         for (j = 0; j < n; ++j) {
1353                                 target = start + cli_addr + (gint32)read32 (ip);
1354                                 get_bb (td, cbb, target);
1355                                 ip += 4;
1356                         }
1357                         cbb = get_bb (td, cbb, ip);
1358                         break;
1359                 }
1360                 case MonoInlineR:
1361                 case MonoInlineI8:
1362                         ip += 9;
1363                         break;
1364                 default:
1365                         g_assert_not_reached ();
1366                 }
1367         }
1368 }
1369
1370 static void
1371 interp_save_debug_info (InterpMethod *rtm, MonoMethodHeader *header, TransformData *td, GArray *line_numbers)
1372 {
1373         MonoDebugMethodJitInfo *dinfo;
1374         int i;
1375
1376         if (!mono_debug_enabled ())
1377                 return;
1378
1379         /*
1380          * We save the debug info in the same way the JIT does it, treating the interpreter IR as the native code.
1381          */
1382
1383         dinfo = g_new0 (MonoDebugMethodJitInfo, 1);
1384         dinfo->num_params = rtm->param_count;
1385         dinfo->params = g_new0 (MonoDebugVarInfo, dinfo->num_params);
1386         dinfo->num_locals = header->num_locals;
1387         dinfo->locals = g_new0 (MonoDebugVarInfo, header->num_locals);
1388         dinfo->code_start = (guint8*)rtm->code;
1389         dinfo->code_size = td->new_ip - td->new_code;
1390         dinfo->epilogue_begin = 0;
1391         dinfo->has_var_info = TRUE;
1392         dinfo->num_line_numbers = line_numbers->len;
1393         dinfo->line_numbers = g_new0 (MonoDebugLineNumberEntry, dinfo->num_line_numbers);
1394
1395         for (i = 0; i < dinfo->num_params; i++) {
1396                 MonoDebugVarInfo *var = &dinfo->params [i];
1397                 var->type = rtm->param_types [i];
1398         }
1399         for (i = 0; i < dinfo->num_locals; i++) {
1400                 MonoDebugVarInfo *var = &dinfo->locals [i];
1401                 var->type = header->locals [i];
1402         }
1403
1404         for (i = 0; i < dinfo->num_line_numbers; i++)
1405                 dinfo->line_numbers [i] = g_array_index (line_numbers, MonoDebugLineNumberEntry, i);
1406         mono_debug_add_method (rtm->method, dinfo, mono_domain_get ());
1407
1408         mono_debug_free_method_jit_info (dinfo);
1409 }
1410
1411 /* Same as the code in seq-points.c */
1412 static void
1413 insert_pred_seq_point (SeqPoint *last_sp, SeqPoint *sp, GSList **next)
1414 {
1415         GSList *l;
1416         int src_index = last_sp->next_offset;
1417         int dst_index = sp->next_offset;
1418
1419         /* bb->in_bb might contain duplicates */
1420         for (l = next [src_index]; l; l = l->next)
1421                 if (GPOINTER_TO_UINT (l->data) == dst_index)
1422                         break;
1423         if (!l)
1424                 next [src_index] = g_slist_append (next [src_index], GUINT_TO_POINTER (dst_index));
1425 }
1426
1427 static void
1428 recursively_make_pred_seq_points (TransformData *td, InterpBasicBlock *bb)
1429 {
1430         const gpointer MONO_SEQ_SEEN_LOOP = GINT_TO_POINTER(-1);
1431         GSList *l;
1432
1433         GArray *predecessors = g_array_new (FALSE, TRUE, sizeof (gpointer));
1434         GHashTable *seen = g_hash_table_new_full (g_direct_hash, NULL, NULL, NULL);
1435
1436         // Insert/remove sentinel into the memoize table to detect loops containing bb
1437         bb->pred_seq_points = MONO_SEQ_SEEN_LOOP;
1438
1439         for (l = bb->preds; l; l = l->next) {
1440                 InterpBasicBlock *in_bb = l->data;
1441
1442                 // This bb has the last seq point, append it and continue
1443                 if (in_bb->last_seq_point != NULL) {
1444                         predecessors = g_array_append_val (predecessors, in_bb->last_seq_point);
1445                         continue;
1446                 }
1447
1448                 // We've looped or handled this before, exit early.
1449                 // No last sequence points to find.
1450                 if (in_bb->pred_seq_points == MONO_SEQ_SEEN_LOOP)
1451                         continue;
1452
1453                 // Take sequence points from incoming basic blocks
1454
1455                 if (in_bb == td->entry_bb)
1456                         continue;
1457
1458                 if (in_bb->pred_seq_points == NULL)
1459                         recursively_make_pred_seq_points (td, in_bb);
1460
1461                 // Union sequence points with incoming bb's
1462                 for (int i=0; i < in_bb->num_pred_seq_points; i++) {
1463                         if (!g_hash_table_lookup (seen, in_bb->pred_seq_points [i])) {
1464                                 g_array_append_val (predecessors, in_bb->pred_seq_points [i]);
1465                                 g_hash_table_insert (seen, in_bb->pred_seq_points [i], (gpointer)&MONO_SEQ_SEEN_LOOP);
1466                         }
1467                 }
1468                 // predecessors = g_array_append_vals (predecessors, in_bb->pred_seq_points, in_bb->num_pred_seq_points);
1469         }
1470
1471         g_hash_table_destroy (seen);
1472
1473         if (predecessors->len != 0) {
1474                 bb->pred_seq_points = mono_mempool_alloc0 (td->mempool, sizeof (SeqPoint *) * predecessors->len);
1475                 bb->num_pred_seq_points = predecessors->len;
1476
1477                 for (int newer = 0; newer < bb->num_pred_seq_points; newer++) {
1478                         bb->pred_seq_points [newer] = g_array_index (predecessors, gpointer, newer);
1479                 }
1480         }
1481
1482         g_array_free (predecessors, TRUE);
1483 }
1484
1485 static void
1486 collect_pred_seq_points (TransformData *td, InterpBasicBlock *bb, SeqPoint *seqp, GSList **next)
1487 {
1488         // Doesn't have a last sequence point, must find from incoming basic blocks
1489         if (bb->pred_seq_points == NULL && bb != td->entry_bb)
1490                 recursively_make_pred_seq_points (td, bb);
1491
1492         for (int i = 0; i < bb->num_pred_seq_points; i++)
1493                 insert_pred_seq_point (bb->pred_seq_points [i], seqp, next);
1494
1495         return;
1496 }
1497
1498 static void
1499 save_seq_points (TransformData *td)
1500 {
1501         InterpMethod *rtm = td->rtm;
1502         GByteArray *array;
1503         int i, seq_info_size;
1504         MonoSeqPointInfo *info;
1505         MonoDomain *domain = mono_domain_get ();
1506         GSList **next = NULL;
1507         GList *bblist;
1508
1509         if (!td->gen_sdb_seq_points)
1510                 return;
1511
1512         /*
1513          * For each sequence point, compute the list of sequence points immediately
1514          * following it, this is needed to implement 'step over' in the debugger agent.
1515          * Similar to the code in mono_save_seq_point_info ().
1516          */
1517         for (i = 0; i < td->seq_points->len; ++i) {
1518                 SeqPoint *sp = g_ptr_array_index (td->seq_points, i);
1519
1520                 /* Store the seq point index here temporarily */
1521                 sp->next_offset = i;
1522         }
1523         next = mono_mempool_alloc0 (td->mempool, sizeof (GList*) * td->seq_points->len);
1524         for (bblist = td->basic_blocks; bblist; bblist = bblist->next) {
1525                 InterpBasicBlock *bb = bblist->data;
1526
1527                 GSList *bb_seq_points = g_slist_reverse (bb->seq_points);
1528                 SeqPoint *last = NULL;
1529                 for (GSList *l = bb_seq_points; l; l = l->next) {
1530                         SeqPoint *sp = l->data;
1531
1532                         if (sp->il_offset == METHOD_ENTRY_IL_OFFSET || sp->il_offset == METHOD_EXIT_IL_OFFSET)
1533                                 /* Used to implement method entry/exit events */
1534                                 continue;
1535
1536                         if (last != NULL) {
1537                                 /* Link with the previous seq point in the same bb */
1538                                 next [last->next_offset] = g_slist_append_mempool (td->mempool, next [last->next_offset], GINT_TO_POINTER (sp->next_offset));
1539                         } else {
1540                                 /* Link with the last bb in the previous bblocks */
1541                                 collect_pred_seq_points (td, bb, sp, next);
1542                         }
1543                         last = sp;
1544                 }
1545         }
1546
1547         /* Serialize the seq points into a byte array */
1548         array = g_byte_array_new ();
1549         SeqPoint zero_seq_point = {0};
1550         SeqPoint* last_seq_point = &zero_seq_point;
1551         for (i = 0; i < td->seq_points->len; ++i) {
1552                 SeqPoint *sp = (SeqPoint*)g_ptr_array_index (td->seq_points, i);
1553
1554                 sp->next_offset = 0;
1555                 if (mono_seq_point_info_add_seq_point (array, sp, last_seq_point, next [i], TRUE))
1556                         last_seq_point = sp;
1557         }
1558
1559         if (td->verbose_level) {
1560                 g_print ("\nSEQ POINT MAP FOR %s: \n", td->method->name);
1561
1562                 for (i = 0; i < td->seq_points->len; ++i) {
1563                         SeqPoint *sp = (SeqPoint*)g_ptr_array_index (td->seq_points, i);
1564                         GSList *l;
1565
1566                         if (!next [i])
1567                                 continue;
1568
1569                         g_print ("\tIL0x%x[0x%0x] ->", sp->il_offset, sp->native_offset);
1570                         for (l = next [i]; l; l = l->next) {
1571                                 int next_index = GPOINTER_TO_UINT (l->data);
1572                                 g_print (" IL0x%x", ((SeqPoint*)g_ptr_array_index (td->seq_points, next_index))->il_offset);
1573                         }
1574                         g_print ("\n");
1575                 }
1576         }
1577
1578         info = mono_seq_point_info_new (array->len, TRUE, array->data, TRUE, &seq_info_size);
1579         InterlockedAdd (&mono_jit_stats.allocated_seq_points_size, seq_info_size);
1580
1581         g_byte_array_free (array, TRUE);
1582
1583         mono_domain_lock (domain);
1584         g_hash_table_insert (domain_jit_info (domain)->seq_points, rtm->method, info);
1585         mono_domain_unlock (domain);
1586 }
1587
1588 static void
1589 emit_seq_point (TransformData *td, int il_offset, InterpBasicBlock *cbb, gboolean nonempty_stack)
1590 {
1591         SeqPoint *seqp;
1592
1593         seqp = mono_mempool_alloc0 (td->mempool, sizeof (SeqPoint));
1594         seqp->il_offset = il_offset;
1595         seqp->native_offset = (guint8*)td->new_ip - (guint8*)td->new_code;
1596         if (nonempty_stack)
1597                 seqp->flags |= MONO_SEQ_POINT_FLAG_NONEMPTY_STACK;
1598
1599         ADD_CODE (td, MINT_SDB_SEQ_POINT);
1600         g_ptr_array_add (td->seq_points, seqp);
1601
1602         cbb->seq_points = g_slist_prepend_mempool (td->mempool, cbb->seq_points, seqp);
1603         cbb->last_seq_point = seqp;
1604 }
1605
1606 #define BARRIER_IF_VOLATILE(td) \
1607         do { \
1608                 if (volatile_) { \
1609                         ADD_CODE (td, MINT_MONO_MEMORY_BARRIER); \
1610                         volatile_ = FALSE; \
1611                 } \
1612         } while (0)
1613
1614 static void
1615 generate (MonoMethod *method, InterpMethod *rtm, unsigned char *is_bb_start, MonoGenericContext *generic_context)
1616 {
1617         MonoMethodHeader *header = mono_method_get_header (method);
1618         MonoMethodSignature *signature = mono_method_signature (method);
1619         MonoImage *image = method->klass->image;
1620         MonoDomain *domain = rtm->domain;
1621         MonoClass *constrained_class = NULL;
1622         MonoError error;
1623         int offset, mt, i, i32;
1624         gboolean readonly = FALSE;
1625         gboolean volatile_ = FALSE;
1626         MonoClass *klass;
1627         MonoClassField *field;
1628         const unsigned char *end;
1629         int new_in_start_offset;
1630         int body_start_offset;
1631         int target;
1632         guint32 token;
1633         TransformData transform_data;
1634         TransformData *td;
1635         int generating_code = 1;
1636         GArray *line_numbers;
1637         MonoDebugMethodInfo *minfo;
1638         MonoBitSet *seq_point_locs = NULL;
1639         MonoBitSet *seq_point_set_locs = NULL;
1640         gboolean sym_seq_points = FALSE;
1641         InterpBasicBlock *bb_exit = NULL;
1642         static gboolean verbose_method_inited;
1643         static char* verbose_method_name;
1644
1645         if (!verbose_method_inited) {
1646                 verbose_method_name = getenv ("MONO_VERBOSE_METHOD");
1647                 verbose_method_inited = TRUE;
1648         }
1649
1650         memset (&transform_data, 0, sizeof(transform_data));
1651         td = &transform_data;
1652
1653         td->method = method;
1654         td->rtm = rtm;
1655         td->is_bb_start = is_bb_start;
1656         td->il_code = header->code;
1657         td->code_size = header->code_size;
1658         td->header = header;
1659         td->max_code_size = td->code_size;
1660         td->new_code = (unsigned short *)g_malloc(td->max_code_size * sizeof(gushort));
1661         td->new_code_end = td->new_code + td->max_code_size;
1662         td->mempool = mono_mempool_new ();
1663         td->in_offsets = g_malloc0(header->code_size * sizeof(int));
1664         td->stack_state = g_malloc0(header->code_size * sizeof(StackInfo *));
1665         td->stack_height = g_malloc(header->code_size * sizeof(int));
1666         td->vt_stack_size = g_malloc(header->code_size * sizeof(int));
1667         td->n_data_items = 0;
1668         td->max_data_items = 0;
1669         td->data_items = NULL;
1670         td->data_hash = g_hash_table_new (NULL, NULL);
1671         td->clause_indexes = g_malloc (header->code_size * sizeof (int));
1672         td->gen_sdb_seq_points = debug_options.gen_sdb_seq_points;
1673         td->seq_points = g_ptr_array_new ();
1674         td->relocs = g_ptr_array_new ();
1675         td->verbose_level = mono_interp_traceopt;
1676         rtm->data_items = td->data_items;
1677         for (i = 0; i < header->code_size; i++) {
1678                 td->stack_height [i] = -1;
1679                 td->clause_indexes [i] = -1;
1680         }
1681
1682         if (verbose_method_name) {
1683                 const char *name = verbose_method_name;
1684
1685                 if ((strchr (name, '.') > name) || strchr (name, ':')) {
1686                         MonoMethodDesc *desc;
1687
1688                         desc = mono_method_desc_new (name, TRUE);
1689                         if (mono_method_desc_full_match (desc, method)) {
1690                                 td->verbose_level = 4;
1691                         }
1692                         mono_method_desc_free (desc);
1693                 } else {
1694                         if (strcmp (method->name, name) == 0)
1695                                 td->verbose_level = 4;
1696                 }
1697         }
1698
1699         if (td->gen_sdb_seq_points) {
1700                 get_basic_blocks (td);
1701
1702                 minfo = mono_debug_lookup_method (method);
1703
1704                 if (minfo) {
1705                         MonoSymSeqPoint *sps;
1706                         int i, n_il_offsets;
1707
1708                         mono_debug_get_seq_points (minfo, NULL, NULL, NULL, &sps, &n_il_offsets);
1709                         // FIXME: Free
1710                         seq_point_locs = mono_bitset_mem_new (mono_mempool_alloc0 (td->mempool, mono_bitset_alloc_size (header->code_size, 0)), header->code_size, 0);
1711                         seq_point_set_locs = mono_bitset_mem_new (mono_mempool_alloc0 (td->mempool, mono_bitset_alloc_size (header->code_size, 0)), header->code_size, 0);
1712                         sym_seq_points = TRUE;
1713
1714                         for (i = 0; i < n_il_offsets; ++i) {
1715                                 if (sps [i].il_offset < header->code_size)
1716                                         mono_bitset_set_fast (seq_point_locs, sps [i].il_offset);
1717                         }
1718                         g_free (sps);
1719                 } else if (!method->wrapper_type && !method->dynamic && mono_debug_image_has_debug_info (method->klass->image)) {
1720                         /* Methods without line number info like auto-generated property accessors */
1721                         seq_point_locs = mono_bitset_new (header->code_size, 0);
1722                         seq_point_set_locs = mono_bitset_new (header->code_size, 0);
1723                         sym_seq_points = TRUE;
1724                 }
1725         }
1726
1727         td->new_ip = td->new_code;
1728         td->last_new_ip = NULL;
1729
1730         td->stack = g_malloc0 ((header->max_stack + 1) * sizeof (td->stack [0]));
1731         td->sp = td->stack;
1732         td->max_stack_height = 0;
1733
1734         line_numbers = g_array_new (FALSE, TRUE, sizeof (MonoDebugLineNumberEntry));
1735
1736         for (i = 0; i < header->num_clauses; i++) {
1737                 MonoExceptionClause *c = header->clauses + i;
1738                 td->stack_height [c->handler_offset] = 0;
1739                 td->vt_stack_size [c->handler_offset] = 0;
1740                 td->is_bb_start [c->handler_offset] = 1;
1741
1742                 td->stack_height [c->handler_offset] = 1;
1743                 td->stack_state [c->handler_offset] = g_malloc0(sizeof(StackInfo));
1744                 td->stack_state [c->handler_offset][0].type = STACK_TYPE_O;
1745                 td->stack_state [c->handler_offset][0].klass = NULL; /*FIX*/
1746
1747                 if (c->flags & MONO_EXCEPTION_CLAUSE_FILTER) {
1748                         td->stack_height [c->data.filter_offset] = 0;
1749                         td->vt_stack_size [c->data.filter_offset] = 0;
1750                         td->is_bb_start [c->data.filter_offset] = 1;
1751
1752                         td->stack_height [c->data.filter_offset] = 1;
1753                         td->stack_state [c->data.filter_offset] = g_malloc0(sizeof(StackInfo));
1754                         td->stack_state [c->data.filter_offset][0].type = STACK_TYPE_O;
1755                         td->stack_state [c->data.filter_offset][0].klass = NULL; /*FIX*/
1756                 }
1757
1758                 for (int j = c->handler_offset; j < c->handler_offset + c->handler_len; ++j) {
1759                         if (td->clause_indexes [j] == -1)
1760                                 td->clause_indexes [j] = i;
1761                 }
1762         }
1763
1764         td->ip = header->code;
1765         end = td->ip + header->code_size;
1766
1767         if (td->verbose_level) {
1768                 char *tmp = mono_disasm_code (NULL, method, td->ip, end);
1769                 char *name = mono_method_full_name (method, TRUE);
1770                 g_print ("Method %s, original code:\n", name);
1771                 g_print ("%s\n", tmp);
1772                 g_free (tmp);
1773                 g_free (name);
1774         }
1775
1776         if (signature->hasthis)
1777                 store_inarg (td, 0);
1778         for (i = 0; i < signature->param_count; i++)
1779                 store_inarg (td, i + !!signature->hasthis);
1780
1781         body_start_offset = td->new_ip - td->new_code;
1782
1783         for (i = 0; i < header->num_locals; i++) {
1784                 int mt = mint_type(header->locals [i]);
1785                 if (mt == MINT_TYPE_VT || mt == MINT_TYPE_O || mt == MINT_TYPE_P) {
1786                         ADD_CODE(td, MINT_INITLOCALS);
1787                         break;
1788                 }
1789         }
1790
1791         if (rtm->prof_flags & MONO_PROFILER_CALL_INSTRUMENTATION_ENTER)
1792                 ADD_CODE (td, MINT_PROF_ENTER);
1793
1794         if (sym_seq_points) {
1795                 InterpBasicBlock *cbb = td->offset_to_bb [0];
1796                 g_assert (cbb);
1797                 emit_seq_point (td, METHOD_ENTRY_IL_OFFSET, cbb, FALSE);
1798         }
1799
1800         while (td->ip < end) {
1801                 int in_offset;
1802
1803                 g_assert (td->sp >= td->stack);
1804                 g_assert (td->vt_sp < 0x10000000);
1805                 in_offset = td->ip - header->code;
1806                 td->in_offsets [in_offset] = td->new_ip - td->new_code;
1807                 new_in_start_offset = td->new_ip - td->new_code;
1808                 td->in_start = td->ip;
1809
1810                 MonoDebugLineNumberEntry lne;
1811                 lne.native_offset = (guint8*)td->new_ip - (guint8*)td->new_code;
1812                 lne.il_offset = in_offset;
1813                 g_array_append_val (line_numbers, lne);
1814
1815                 if (td->stack_height [in_offset] >= 0) {
1816                         g_assert (is_bb_start [in_offset]);
1817                         if (td->stack_height [in_offset] > 0)
1818                                 memcpy (td->stack, td->stack_state [in_offset], td->stack_height [in_offset] * sizeof(td->stack [0]));
1819                         td->sp = td->stack + td->stack_height [in_offset];
1820                         td->vt_sp = td->vt_stack_size [in_offset];
1821                 }
1822                 if (is_bb_start [in_offset]) {
1823                         generating_code = 1;
1824                 }
1825                 if (!generating_code) {
1826                         while (td->ip < end && !is_bb_start [td->ip - td->il_code])
1827                                 ++td->ip;
1828                         continue;
1829                 }
1830                 if (td->verbose_level > 1) {
1831                         printf("IL_%04lx %s %-10s -> IL_%04lx, sp %ld, %s %-12s vt_sp %u (max %u)\n", 
1832                                 td->ip - td->il_code,
1833                                 td->is_bb_start [td->ip - td->il_code] == 3 ? "<>" :
1834                                 td->is_bb_start [td->ip - td->il_code] == 2 ? "< " :
1835                                 td->is_bb_start [td->ip - td->il_code] == 1 ? " >" : "  ",
1836                                 mono_opcode_name (*td->ip), td->new_ip - td->new_code, td->sp - td->stack, 
1837                                 td->sp > td->stack ? stack_type_string [td->sp [-1].type] : "  ",
1838                                 (td->sp > td->stack && (td->sp [-1].type == STACK_TYPE_O || td->sp [-1].type == STACK_TYPE_VT)) ? (td->sp [-1].klass == NULL ? "?" : td->sp [-1].klass->name) : "",
1839                                 td->vt_sp, td->max_vt_sp);
1840                 }
1841
1842                 if (sym_seq_points && mono_bitset_test_fast (seq_point_locs, td->ip - header->code)) {
1843                         InterpBasicBlock *cbb = td->offset_to_bb [td->ip - header->code];
1844                         g_assert (cbb);
1845
1846                         /*
1847                          * Make methods interruptable at the beginning, and at the targets of
1848                          * backward branches.
1849                          */
1850                         if (in_offset == 0 || g_slist_length (cbb->preds) > 1)
1851                                 ADD_CODE (td, MINT_SDB_INTR_LOC);
1852
1853                         emit_seq_point (td, in_offset, cbb, FALSE);
1854
1855                         mono_bitset_set_fast (seq_point_set_locs, td->ip - header->code);
1856                 }
1857
1858                 if (sym_seq_points)
1859                         bb_exit = td->offset_to_bb [td->ip - header->code];
1860
1861                 switch (*td->ip) {
1862                 case CEE_NOP: 
1863                         /* lose it */
1864                         ++td->ip;
1865                         break;
1866                 case CEE_BREAK:
1867                         SIMPLE_OP(td, MINT_BREAK);
1868                         break;
1869                 case CEE_LDARG_0:
1870                 case CEE_LDARG_1:
1871                 case CEE_LDARG_2:
1872                 case CEE_LDARG_3:
1873                         load_arg (td, *td->ip - CEE_LDARG_0);
1874                         ++td->ip;
1875                         break;
1876                 case CEE_LDLOC_0:
1877                 case CEE_LDLOC_1:
1878                 case CEE_LDLOC_2:
1879                 case CEE_LDLOC_3:
1880                         load_local (td, *td->ip - CEE_LDLOC_0);
1881                         ++td->ip;
1882                         break;
1883                 case CEE_STLOC_0:
1884                 case CEE_STLOC_1:
1885                 case CEE_STLOC_2:
1886                 case CEE_STLOC_3:
1887                         store_local (td, *td->ip - CEE_STLOC_0);
1888                         ++td->ip;
1889                         break;
1890                 case CEE_LDARG_S:
1891                         load_arg (td, ((guint8 *)td->ip)[1]);
1892                         td->ip += 2;
1893                         break;
1894                 case CEE_LDARGA_S: {
1895                         /* NOTE: n includes this */
1896                         int n = ((guint8 *) td->ip) [1];
1897                         ADD_CODE (td, MINT_LDARGA);
1898                         ADD_CODE (td, td->rtm->arg_offsets [n]);
1899                         PUSH_SIMPLE_TYPE(td, STACK_TYPE_MP);
1900                         td->ip += 2;
1901                         break;
1902                 }
1903                 case CEE_STARG_S:
1904                         store_arg (td, ((guint8 *)td->ip)[1]);
1905                         td->ip += 2;
1906                         break;
1907                 case CEE_LDLOC_S:
1908                         load_local (td, ((guint8 *)td->ip)[1]);
1909                         td->ip += 2;
1910                         break;
1911                 case CEE_LDLOCA_S:
1912                         ADD_CODE(td, MINT_LDLOCA_S);
1913                         ADD_CODE(td, td->rtm->local_offsets [((guint8 *)td->ip)[1]]);
1914                         PUSH_SIMPLE_TYPE(td, STACK_TYPE_MP);
1915                         td->ip += 2;
1916                         break;
1917                 case CEE_STLOC_S:
1918                         store_local (td, ((guint8 *)td->ip)[1]);
1919                         td->ip += 2;
1920                         break;
1921                 case CEE_LDNULL: 
1922                         SIMPLE_OP(td, MINT_LDNULL);
1923                         PUSH_TYPE(td, STACK_TYPE_O, NULL);
1924                         break;
1925                 case CEE_LDC_I4_M1:
1926                         SIMPLE_OP(td, MINT_LDC_I4_M1);
1927                         PUSH_SIMPLE_TYPE(td, STACK_TYPE_I4);
1928                         break;
1929                 case CEE_LDC_I4_0:
1930                         if (!td->is_bb_start[td->ip + 1 - td->il_code] && td->ip [1] == 0xfe && td->ip [2] == CEE_CEQ && 
1931                                 td->sp > td->stack && td->sp [-1].type == STACK_TYPE_I4) {
1932                                 SIMPLE_OP(td, MINT_CEQ0_I4);
1933                                 td->ip += 2;
1934                         } else {
1935                                 SIMPLE_OP(td, MINT_LDC_I4_0);
1936                                 PUSH_SIMPLE_TYPE(td, STACK_TYPE_I4);
1937                         }
1938                         break;
1939                 case CEE_LDC_I4_1:
1940                         if (!td->is_bb_start[td->ip + 1 - td->il_code] && 
1941                                 (td->ip [1] == CEE_ADD || td->ip [1] == CEE_SUB) && td->sp [-1].type == STACK_TYPE_I4) {
1942                                 ADD_CODE(td, td->ip [1] == CEE_ADD ? MINT_ADD1_I4 : MINT_SUB1_I4);
1943                                 td->ip += 2;
1944                         } else {
1945                                 SIMPLE_OP(td, MINT_LDC_I4_1);
1946                                 PUSH_SIMPLE_TYPE(td, STACK_TYPE_I4);
1947                         }
1948                         break;
1949                 case CEE_LDC_I4_2:
1950                 case CEE_LDC_I4_3:
1951                 case CEE_LDC_I4_4:
1952                 case CEE_LDC_I4_5:
1953                 case CEE_LDC_I4_6:
1954                 case CEE_LDC_I4_7:
1955                 case CEE_LDC_I4_8:
1956                         SIMPLE_OP(td, (*td->ip - CEE_LDC_I4_0) + MINT_LDC_I4_0);
1957                         PUSH_SIMPLE_TYPE(td, STACK_TYPE_I4);
1958                         break;
1959                 case CEE_LDC_I4_S: 
1960                         ADD_CODE(td, MINT_LDC_I4_S);
1961                         ADD_CODE(td, ((gint8 *) td->ip) [1]);
1962                         td->ip += 2;
1963                         PUSH_SIMPLE_TYPE(td, STACK_TYPE_I4);
1964                         break;
1965                 case CEE_LDC_I4:
1966                         i32 = read32 (td->ip + 1);
1967                         ADD_CODE(td, MINT_LDC_I4);
1968                         WRITE32(td, &i32);
1969                         td->ip += 5;
1970                         PUSH_SIMPLE_TYPE(td, STACK_TYPE_I4);
1971                         break;
1972                 case CEE_LDC_I8: {
1973                         gint64 val = read64 (td->ip + 1);
1974                         ADD_CODE(td, MINT_LDC_I8);
1975                         WRITE64(td, &val);
1976                         td->ip += 9;
1977                         PUSH_SIMPLE_TYPE(td, STACK_TYPE_I8);
1978                         break;
1979                 }
1980                 case CEE_LDC_R4: {
1981                         float val;
1982                         readr4 (td->ip + 1, &val);
1983                         ADD_CODE(td, MINT_LDC_R4);
1984                         WRITE32(td, &val);
1985                         td->ip += 5;
1986                         PUSH_SIMPLE_TYPE(td, STACK_TYPE_R8);
1987                         break;
1988                 }
1989                 case CEE_LDC_R8: {
1990                         double val;
1991                         readr8 (td->ip + 1, &val);
1992                         ADD_CODE(td, MINT_LDC_R8);
1993                         WRITE64(td, &val);
1994                         td->ip += 9;
1995                         PUSH_SIMPLE_TYPE(td, STACK_TYPE_R8);
1996                         break;
1997                 }
1998                 case CEE_DUP: {
1999                         int type = td->sp [-1].type;
2000                         MonoClass *klass = td->sp [-1].klass;
2001                         if (td->sp [-1].type == STACK_TYPE_VT) {
2002                                 gint32 size = mono_class_value_size (klass, NULL);
2003                                 PUSH_VT(td, size);
2004                                 ADD_CODE(td, MINT_DUP_VT);
2005                                 WRITE32(td, &size);
2006                                 td->ip ++;
2007                         } else 
2008                                 SIMPLE_OP(td, MINT_DUP);
2009                         PUSH_TYPE(td, type, klass);
2010                         break;
2011                 }
2012                 case CEE_POP:
2013                         CHECK_STACK(td, 1);
2014                         SIMPLE_OP(td, MINT_POP);
2015                         ADD_CODE (td, 0);
2016                         if (td->sp [-1].type == STACK_TYPE_VT) {
2017                                 int size = mono_class_value_size (td->sp [-1].klass, NULL);
2018                                 size = (size + 7) & ~7;
2019                                 ADD_CODE(td, MINT_VTRESULT);
2020                                 ADD_CODE(td, 0);
2021                                 WRITE32(td, &size);
2022                                 td->vt_sp -= size;
2023                         }
2024                         --td->sp;
2025                         break;
2026                 case CEE_JMP: {
2027                         MonoMethod *m;
2028                         if (td->sp > td->stack)
2029                                 g_warning ("CEE_JMP: stack must be empty");
2030                         token = read32 (td->ip + 1);
2031                         m = mono_get_method_full (image, token, NULL, generic_context);
2032                         ADD_CODE (td, MINT_JMP);
2033                         ADD_CODE (td, get_data_item_index (td, mono_interp_get_imethod (domain, m, &error)));
2034                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
2035                         td->ip += 5;
2036                         break;
2037                 }
2038                 case CEE_CALLVIRT: /* Fall through */
2039                 case CEE_CALLI:    /* Fall through */
2040                 case CEE_CALL: {
2041                         gboolean need_seq_point = FALSE;
2042
2043                         if (sym_seq_points && !mono_bitset_test_fast (seq_point_locs, td->ip + 5 - header->code))
2044                                 need_seq_point = TRUE;
2045
2046                         interp_transform_call (td, method, NULL, domain, generic_context, is_bb_start, body_start_offset, constrained_class, readonly);
2047
2048                         if (need_seq_point) {
2049                                 InterpBasicBlock *cbb = td->offset_to_bb [td->ip - header->code];
2050                                 g_assert (cbb);
2051
2052                                 emit_seq_point (td, td->ip - header->code, cbb, TRUE);
2053                         }
2054
2055                         constrained_class = NULL;
2056                         readonly = FALSE;
2057                         break;
2058                 }
2059                 case CEE_RET: {
2060                         int vt_size = 0;
2061                         if (signature->ret->type != MONO_TYPE_VOID) {
2062                                 --td->sp;
2063                                 MonoClass *klass = mono_class_from_mono_type (signature->ret);
2064                                 if (mint_type (&klass->byval_arg) == MINT_TYPE_VT) {
2065                                         vt_size = mono_class_value_size (klass, NULL);
2066                                         vt_size = (vt_size + 7) & ~7;
2067                                 }
2068                         }
2069                         if (td->sp > td->stack)
2070                                 g_warning ("%s.%s: CEE_RET: more values on stack: %d", td->method->klass->name, td->method->name, td->sp - td->stack);
2071                         if (td->vt_sp != vt_size)
2072                                 g_error ("%s.%s: CEE_RET: value type stack: %d vs. %d", td->method->klass->name, td->method->name, td->vt_sp, vt_size);
2073
2074                         if (sym_seq_points) {
2075                                 InterpBasicBlock *cbb = td->offset_to_bb [td->ip - header->code];
2076                                 g_assert (cbb);
2077                                 emit_seq_point (td, METHOD_EXIT_IL_OFFSET, bb_exit, FALSE);
2078                         }
2079
2080                         if (vt_size == 0)
2081                                 SIMPLE_OP(td, signature->ret->type == MONO_TYPE_VOID ? MINT_RET_VOID : MINT_RET);
2082                         else {
2083                                 ADD_CODE(td, MINT_RET_VT);
2084                                 WRITE32(td, &vt_size);
2085                                 ++td->ip;
2086                         }
2087                         generating_code = 0;
2088                         break;
2089                 }
2090                 case CEE_BR:
2091                         handle_branch (td, MINT_BR_S, MINT_BR, 5 + read32 (td->ip + 1));
2092                         td->ip += 5;
2093                         generating_code = 0;
2094                         break;
2095                 case CEE_BR_S:
2096                         handle_branch (td, MINT_BR_S, MINT_BR, 2 + (gint8)td->ip [1]);
2097                         td->ip += 2;
2098                         generating_code = 0;
2099                         break;
2100                 case CEE_BRFALSE:
2101                         one_arg_branch (td, MINT_BRFALSE_I4, 5 + read32 (td->ip + 1));
2102                         td->ip += 5;
2103                         break;
2104                 case CEE_BRFALSE_S:
2105                         one_arg_branch (td, MINT_BRFALSE_I4, 2 + (gint8)td->ip [1]);
2106                         td->ip += 2;
2107                         break;
2108                 case CEE_BRTRUE:
2109                         one_arg_branch (td, MINT_BRTRUE_I4, 5 + read32 (td->ip + 1));
2110                         td->ip += 5;
2111                         break;
2112                 case CEE_BRTRUE_S:
2113                         one_arg_branch (td, MINT_BRTRUE_I4, 2 + (gint8)td->ip [1]);
2114                         td->ip += 2;
2115                         break;
2116                 case CEE_BEQ:
2117                         two_arg_branch (td, MINT_BEQ_I4, 5 + read32 (td->ip + 1));
2118                         td->ip += 5;
2119                         break;
2120                 case CEE_BEQ_S:
2121                         two_arg_branch (td, MINT_BEQ_I4, 2 + (gint8) td->ip [1]);
2122                         td->ip += 2;
2123                         break;
2124                 case CEE_BGE:
2125                         two_arg_branch (td, MINT_BGE_I4, 5 + read32 (td->ip + 1));
2126                         td->ip += 5;
2127                         break;
2128                 case CEE_BGE_S:
2129                         two_arg_branch (td, MINT_BGE_I4, 2 + (gint8) td->ip [1]);
2130                         td->ip += 2;
2131                         break;
2132                 case CEE_BGT:
2133                         two_arg_branch (td, MINT_BGT_I4, 5 + read32 (td->ip + 1));
2134                         td->ip += 5;
2135                         break;
2136                 case CEE_BGT_S:
2137                         two_arg_branch (td, MINT_BGT_I4, 2 + (gint8) td->ip [1]);
2138                         td->ip += 2;
2139                         break;
2140                 case CEE_BLT:
2141                         two_arg_branch (td, MINT_BLT_I4, 5 + read32 (td->ip + 1));
2142                         td->ip += 5;
2143                         break;
2144                 case CEE_BLT_S:
2145                         two_arg_branch (td, MINT_BLT_I4, 2 + (gint8) td->ip [1]);
2146                         td->ip += 2;
2147                         break;
2148                 case CEE_BLE:
2149                         two_arg_branch (td, MINT_BLE_I4, 5 + read32 (td->ip + 1));
2150                         td->ip += 5;
2151                         break;
2152                 case CEE_BLE_S:
2153                         two_arg_branch (td, MINT_BLE_I4, 2 + (gint8) td->ip [1]);
2154                         td->ip += 2;
2155                         break;
2156                 case CEE_BNE_UN:
2157                         two_arg_branch (td, MINT_BNE_UN_I4, 5 + read32 (td->ip + 1));
2158                         td->ip += 5;
2159                         break;
2160                 case CEE_BNE_UN_S:
2161                         two_arg_branch (td, MINT_BNE_UN_I4, 2 + (gint8) td->ip [1]);
2162                         td->ip += 2;
2163                         break;
2164                 case CEE_BGE_UN:
2165                         two_arg_branch (td, MINT_BGE_UN_I4, 5 + read32 (td->ip + 1));
2166                         td->ip += 5;
2167                         break;
2168                 case CEE_BGE_UN_S:
2169                         two_arg_branch (td, MINT_BGE_UN_I4, 2 + (gint8) td->ip [1]);
2170                         td->ip += 2;
2171                         break;
2172                 case CEE_BGT_UN:
2173                         two_arg_branch (td, MINT_BGT_UN_I4, 5 + read32 (td->ip + 1));
2174                         td->ip += 5;
2175                         break;
2176                 case CEE_BGT_UN_S:
2177                         two_arg_branch (td, MINT_BGT_UN_I4, 2 + (gint8) td->ip [1]);
2178                         td->ip += 2;
2179                         break;
2180                 case CEE_BLE_UN:
2181                         two_arg_branch (td, MINT_BLE_UN_I4, 5 + read32 (td->ip + 1));
2182                         td->ip += 5;
2183                         break;
2184                 case CEE_BLE_UN_S:
2185                         two_arg_branch (td, MINT_BLE_UN_I4, 2 + (gint8) td->ip [1]);
2186                         td->ip += 2;
2187                         break;
2188                 case CEE_BLT_UN:
2189                         two_arg_branch (td, MINT_BLT_UN_I4, 5 + read32 (td->ip + 1));
2190                         td->ip += 5;
2191                         break;
2192                 case CEE_BLT_UN_S:
2193                         two_arg_branch (td, MINT_BLT_UN_I4, 2 + (gint8) td->ip [1]);
2194                         td->ip += 2;
2195                         break;
2196                 case CEE_SWITCH: {
2197                         guint32 n;
2198                         const unsigned char *next_ip;
2199                         ++td->ip;
2200                         n = read32 (td->ip);
2201                         ADD_CODE (td, MINT_SWITCH);
2202                         WRITE32 (td, &n);
2203                         td->ip += 4;
2204                         next_ip = td->ip + n * 4;
2205                         --td->sp;
2206                         int stack_height = td->sp - td->stack;
2207                         for (i = 0; i < n; i++) {
2208                                 offset = read32 (td->ip);
2209                                 target = next_ip - td->il_code + offset;
2210                                 if (offset < 0) {
2211 #if DEBUG_INTERP
2212                                         if (stack_height > 0 && stack_height != td->stack_height [target])
2213                                                 g_warning ("SWITCH with back branch and non-empty stack");
2214 #endif
2215                                         target = td->in_offsets [target] - (td->new_ip - td->new_code);
2216                                 } else {
2217                                         td->stack_height [target] = stack_height;
2218                                         td->vt_stack_size [target] = td->vt_sp;
2219                                         if (stack_height > 0)
2220                                                 td->stack_state [target] = g_memdup (td->stack, stack_height * sizeof (td->stack [0]));
2221
2222                                         Reloc *reloc = mono_mempool_alloc0 (td->mempool, sizeof (Reloc));
2223                                         reloc->type = RELOC_SWITCH;
2224                                         reloc->offset = td->new_ip - td->new_code;
2225                                         reloc->target = target;
2226                                         g_ptr_array_add (td->relocs, reloc);
2227                                         target = 0xffff;
2228                                 }
2229                                 WRITE32 (td, &target);
2230                                 td->ip += 4;
2231                         }
2232                         break;
2233                 }
2234                 case CEE_LDIND_I1:
2235                         CHECK_STACK (td, 1);
2236                         SIMPLE_OP (td, MINT_LDIND_I1);
2237                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
2238                         BARRIER_IF_VOLATILE (td);
2239                         break;
2240                 case CEE_LDIND_U1:
2241                         CHECK_STACK (td, 1);
2242                         SIMPLE_OP (td, MINT_LDIND_U1);
2243                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
2244                         BARRIER_IF_VOLATILE (td);
2245                         break;
2246                 case CEE_LDIND_I2:
2247                         CHECK_STACK (td, 1);
2248                         SIMPLE_OP (td, MINT_LDIND_I2);
2249                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
2250                         BARRIER_IF_VOLATILE (td);
2251                         break;
2252                 case CEE_LDIND_U2:
2253                         CHECK_STACK (td, 1);
2254                         SIMPLE_OP (td, MINT_LDIND_U2);
2255                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
2256                         BARRIER_IF_VOLATILE (td);
2257                         break;
2258                 case CEE_LDIND_I4:
2259                         CHECK_STACK (td, 1);
2260                         SIMPLE_OP (td, MINT_LDIND_I4);
2261                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
2262                         BARRIER_IF_VOLATILE (td);
2263                         break;
2264                 case CEE_LDIND_U4:
2265                         CHECK_STACK (td, 1);
2266                         SIMPLE_OP (td, MINT_LDIND_U4);
2267                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
2268                         BARRIER_IF_VOLATILE (td);
2269                         break;
2270                 case CEE_LDIND_I8:
2271                         CHECK_STACK (td, 1);
2272                         SIMPLE_OP (td, MINT_LDIND_I8);
2273                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I8);
2274                         BARRIER_IF_VOLATILE (td);
2275                         break;
2276                 case CEE_LDIND_I:
2277                         CHECK_STACK (td, 1);
2278                         SIMPLE_OP (td, MINT_LDIND_I);
2279                         ADD_CODE (td, 0);
2280                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I);
2281                         BARRIER_IF_VOLATILE (td);
2282                         break;
2283                 case CEE_LDIND_R4:
2284                         CHECK_STACK (td, 1);
2285                         SIMPLE_OP (td, MINT_LDIND_R4);
2286                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_R8);
2287                         BARRIER_IF_VOLATILE (td);
2288                         break;
2289                 case CEE_LDIND_R8:
2290                         CHECK_STACK (td, 1);
2291                         SIMPLE_OP (td, MINT_LDIND_R8);
2292                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_R8);
2293                         BARRIER_IF_VOLATILE (td);
2294                         break;
2295                 case CEE_LDIND_REF:
2296                         CHECK_STACK (td, 1);
2297                         SIMPLE_OP (td, MINT_LDIND_REF);
2298                         BARRIER_IF_VOLATILE (td);
2299                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_O);
2300                         break;
2301                 case CEE_STIND_REF:
2302                         CHECK_STACK (td, 2);
2303                         BARRIER_IF_VOLATILE (td);
2304                         SIMPLE_OP (td, MINT_STIND_REF);
2305                         td->sp -= 2;
2306                         break;
2307                 case CEE_STIND_I1:
2308                         CHECK_STACK (td, 2);
2309                         BARRIER_IF_VOLATILE (td);
2310                         SIMPLE_OP (td, MINT_STIND_I1);
2311                         td->sp -= 2;
2312                         break;
2313                 case CEE_STIND_I2:
2314                         CHECK_STACK (td, 2);
2315                         BARRIER_IF_VOLATILE (td);
2316                         SIMPLE_OP (td, MINT_STIND_I2);
2317                         td->sp -= 2;
2318                         break;
2319                 case CEE_STIND_I4:
2320                         CHECK_STACK (td, 2);
2321                         BARRIER_IF_VOLATILE (td);
2322                         SIMPLE_OP (td, MINT_STIND_I4);
2323                         td->sp -= 2;
2324                         break;
2325                 case CEE_STIND_I:
2326                         CHECK_STACK (td, 2);
2327                         BARRIER_IF_VOLATILE (td);
2328                         SIMPLE_OP (td, MINT_STIND_I);
2329                         td->sp -= 2;
2330                         break;
2331                 case CEE_STIND_I8:
2332                         CHECK_STACK (td, 2);
2333                         BARRIER_IF_VOLATILE (td);
2334                         SIMPLE_OP (td, MINT_STIND_I8);
2335                         td->sp -= 2;
2336                         break;
2337                 case CEE_STIND_R4:
2338                         CHECK_STACK (td, 2);
2339                         BARRIER_IF_VOLATILE (td);
2340                         SIMPLE_OP (td, MINT_STIND_R4);
2341                         td->sp -= 2;
2342                         break;
2343                 case CEE_STIND_R8:
2344                         CHECK_STACK (td, 2);
2345                         BARRIER_IF_VOLATILE (td);
2346                         SIMPLE_OP (td, MINT_STIND_R8);
2347                         td->sp -= 2;
2348                         break;
2349                 case CEE_ADD:
2350                         binary_arith_op(td, MINT_ADD_I4);
2351                         ++td->ip;
2352                         break;
2353                 case CEE_SUB:
2354                         binary_arith_op(td, MINT_SUB_I4);
2355                         ++td->ip;
2356                         break;
2357                 case CEE_MUL:
2358                         binary_arith_op(td, MINT_MUL_I4);
2359                         ++td->ip;
2360                         break;
2361                 case CEE_DIV:
2362                         binary_arith_op(td, MINT_DIV_I4);
2363                         ++td->ip;
2364                         break;
2365                 case CEE_DIV_UN:
2366                         binary_arith_op(td, MINT_DIV_UN_I4);
2367                         ++td->ip;
2368                         break;
2369                 case CEE_REM:
2370                         binary_arith_op (td, MINT_REM_I4);
2371                         ++td->ip;
2372                         break;
2373                 case CEE_REM_UN:
2374                         binary_arith_op (td, MINT_REM_UN_I4);
2375                         ++td->ip;
2376                         break;
2377                 case CEE_AND:
2378                         binary_arith_op (td, MINT_AND_I4);
2379                         ++td->ip;
2380                         break;
2381                 case CEE_OR:
2382                         binary_arith_op (td, MINT_OR_I4);
2383                         ++td->ip;
2384                         break;
2385                 case CEE_XOR:
2386                         binary_arith_op (td, MINT_XOR_I4);
2387                         ++td->ip;
2388                         break;
2389                 case CEE_SHL:
2390                         shift_op (td, MINT_SHL_I4);
2391                         ++td->ip;
2392                         break;
2393                 case CEE_SHR:
2394                         shift_op (td, MINT_SHR_I4);
2395                         ++td->ip;
2396                         break;
2397                 case CEE_SHR_UN:
2398                         shift_op (td, MINT_SHR_UN_I4);
2399                         ++td->ip;
2400                         break;
2401                 case CEE_NEG:
2402                         unary_arith_op (td, MINT_NEG_I4);
2403                         ++td->ip;
2404                         break;
2405                 case CEE_NOT:
2406                         unary_arith_op (td, MINT_NOT_I4);
2407                         ++td->ip;
2408                         break;
2409                 case CEE_CONV_U1:
2410                         CHECK_STACK (td, 1);
2411                         switch (td->sp [-1].type) {
2412                         case STACK_TYPE_R8:
2413                                 ADD_CODE(td, MINT_CONV_U1_R8);
2414                                 break;
2415                         case STACK_TYPE_I4:
2416                                 ADD_CODE(td, MINT_CONV_U1_I4);
2417                                 break;
2418                         case STACK_TYPE_I8:
2419                                 ADD_CODE(td, MINT_CONV_U1_I8);
2420                                 break;
2421                         default:
2422                                 g_assert_not_reached ();
2423                         }
2424                         ++td->ip;
2425                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
2426                         break;
2427                 case CEE_CONV_I1:
2428                         CHECK_STACK (td, 1);
2429                         switch (td->sp [-1].type) {
2430                         case STACK_TYPE_R8:
2431                                 ADD_CODE(td, MINT_CONV_I1_R8);
2432                                 break;
2433                         case STACK_TYPE_I4:
2434                                 ADD_CODE(td, MINT_CONV_I1_I4);
2435                                 break;
2436                         case STACK_TYPE_I8:
2437                                 ADD_CODE(td, MINT_CONV_I1_I8);
2438                                 break;
2439                         default:
2440                                 g_assert_not_reached ();
2441                         }
2442                         ++td->ip;
2443                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
2444                         break;
2445                 case CEE_CONV_U2:
2446                         CHECK_STACK (td, 1);
2447                         switch (td->sp [-1].type) {
2448                         case STACK_TYPE_R8:
2449                                 ADD_CODE(td, MINT_CONV_U2_R8);
2450                                 break;
2451                         case STACK_TYPE_I4:
2452                                 ADD_CODE(td, MINT_CONV_U2_I4);
2453                                 break;
2454                         case STACK_TYPE_I8:
2455                                 ADD_CODE(td, MINT_CONV_U2_I8);
2456                                 break;
2457                         default:
2458                                 g_assert_not_reached ();
2459                         }
2460                         ++td->ip;
2461                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
2462                         break;
2463                 case CEE_CONV_I2:
2464                         CHECK_STACK (td, 1);
2465                         switch (td->sp [-1].type) {
2466                         case STACK_TYPE_R8:
2467                                 ADD_CODE(td, MINT_CONV_I2_R8);
2468                                 break;
2469                         case STACK_TYPE_I4:
2470                                 ADD_CODE(td, MINT_CONV_I2_I4);
2471                                 break;
2472                         case STACK_TYPE_I8:
2473                                 ADD_CODE(td, MINT_CONV_I2_I8);
2474                                 break;
2475                         default:
2476                                 g_assert_not_reached ();
2477                         }
2478                         ++td->ip;
2479                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
2480                         break;
2481                 case CEE_CONV_U:
2482                         CHECK_STACK (td, 1);
2483                         switch (td->sp [-1].type) {
2484                         case STACK_TYPE_R8:
2485 #if SIZEOF_VOID_P == 4
2486                                 ADD_CODE(td, MINT_CONV_U4_R8);
2487 #else
2488                                 ADD_CODE(td, MINT_CONV_U8_R8);
2489 #endif
2490                                 break;
2491                         case STACK_TYPE_I4:
2492 #if SIZEOF_VOID_P == 8
2493                                 ADD_CODE(td, MINT_CONV_U8_I4);
2494 #endif
2495                                 break;
2496                         case STACK_TYPE_I8:
2497 #if SIZEOF_VOID_P == 4
2498                                 ADD_CODE(td, MINT_CONV_U4_I8);
2499 #endif
2500                                 break;
2501                         case STACK_TYPE_MP:
2502                                 break;
2503                         default:
2504                                 g_assert_not_reached ();
2505                         }
2506                         ++td->ip;
2507                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I);
2508                         break;
2509                 case CEE_CONV_I: 
2510                         CHECK_STACK (td, 1);
2511                         switch (td->sp [-1].type) {
2512                         case STACK_TYPE_R8:
2513 #if SIZEOF_VOID_P == 8
2514                                 ADD_CODE(td, MINT_CONV_I8_R8);
2515 #else
2516                                 ADD_CODE(td, MINT_CONV_I4_R8);
2517 #endif
2518                                 break;
2519                         case STACK_TYPE_I4:
2520 #if SIZEOF_VOID_P == 8
2521                                 ADD_CODE(td, MINT_CONV_I8_I4);
2522 #endif
2523                                 break;
2524                         case STACK_TYPE_O:
2525                                 break;
2526                         case STACK_TYPE_MP:
2527                                 break;
2528                         case STACK_TYPE_I8:
2529 #if SIZEOF_VOID_P == 4
2530                                 ADD_CODE(td, MINT_CONV_I4_I8);
2531 #endif
2532                                 break;
2533                         default:
2534                                 g_assert_not_reached ();
2535                         }
2536                         ++td->ip;
2537                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I);
2538                         break;
2539                 case CEE_CONV_U4:
2540                         CHECK_STACK (td, 1);
2541                         switch (td->sp [-1].type) {
2542                         case STACK_TYPE_R8:
2543                                 ADD_CODE(td, MINT_CONV_U4_R8);
2544                                 break;
2545                         case STACK_TYPE_I4:
2546                                 break;
2547                         case STACK_TYPE_I8:
2548                                 ADD_CODE(td, MINT_CONV_U4_I8);
2549                                 break;
2550                         case STACK_TYPE_MP:
2551 #if SIZEOF_VOID_P == 8
2552                                 ADD_CODE(td, MINT_CONV_U4_I8);
2553 #endif
2554                                 break;
2555                         default:
2556                                 g_assert_not_reached ();
2557                         }
2558                         ++td->ip;
2559                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
2560                         break;
2561                 case CEE_CONV_I4:
2562                         CHECK_STACK (td, 1);
2563                         switch (td->sp [-1].type) {
2564                         case STACK_TYPE_R8:
2565                                 ADD_CODE(td, MINT_CONV_I4_R8);
2566                                 break;
2567                         case STACK_TYPE_I4:
2568                                 break;
2569                         case STACK_TYPE_I8:
2570                                 ADD_CODE(td, MINT_CONV_I4_I8);
2571                                 break;
2572                         case STACK_TYPE_MP:
2573 #if SIZEOF_VOID_P == 8
2574                                 ADD_CODE(td, MINT_CONV_I4_I8);
2575 #endif
2576                                 break;
2577                         default:
2578                                 g_assert_not_reached ();
2579                         }
2580                         ++td->ip;
2581                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
2582                         break;
2583                 case CEE_CONV_I8:
2584                         CHECK_STACK (td, 1);
2585                         switch (td->sp [-1].type) {
2586                         case STACK_TYPE_R8:
2587                                 ADD_CODE(td, MINT_CONV_I8_R8);
2588                                 break;
2589                         case STACK_TYPE_I4:
2590                                 ADD_CODE(td, MINT_CONV_I8_I4);
2591                                 break;
2592                         case STACK_TYPE_I8:
2593                                 break;
2594                         case STACK_TYPE_MP:
2595 #if SIZEOF_VOID_P == 4
2596                                 ADD_CODE(td, MINT_CONV_I8_I4);
2597 #endif
2598                                 break;
2599                         default:
2600                                 g_assert_not_reached ();
2601                         }
2602                         ++td->ip;
2603                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I8);
2604                         break;
2605                 case CEE_CONV_R4:
2606                         CHECK_STACK (td, 1);
2607                         switch (td->sp [-1].type) {
2608                         case STACK_TYPE_R8:
2609                                 ADD_CODE(td, MINT_CONV_R4_R8);
2610                                 break;
2611                         case STACK_TYPE_I8:
2612                                 ADD_CODE(td, MINT_CONV_R4_I8);
2613                                 break;
2614                         case STACK_TYPE_I4:
2615                                 ADD_CODE(td, MINT_CONV_R4_I4);
2616                                 break;
2617                         default:
2618                                 g_assert_not_reached ();
2619                         }
2620                         ++td->ip;
2621                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_R8);
2622                         break;
2623                 case CEE_CONV_R8:
2624                         CHECK_STACK (td, 1);
2625                         switch (td->sp [-1].type) {
2626                         case STACK_TYPE_I4:
2627                                 ADD_CODE(td, MINT_CONV_R8_I4);
2628                                 break;
2629                         case STACK_TYPE_I8:
2630                                 ADD_CODE(td, MINT_CONV_R8_I8);
2631                                 break;
2632                         case STACK_TYPE_R8:
2633                                 break;
2634                         default:
2635                                 g_assert_not_reached ();
2636                         }
2637                         ++td->ip;
2638                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_R8);
2639                         break;
2640                 case CEE_CONV_U8:
2641                         CHECK_STACK (td, 1);
2642                         switch (td->sp [-1].type) {
2643                         case STACK_TYPE_I4:
2644                                 ADD_CODE(td, MINT_CONV_U8_I4);
2645                                 break;
2646                         case STACK_TYPE_I8:
2647                                 break;
2648                         case STACK_TYPE_R8:
2649                                 ADD_CODE(td, MINT_CONV_U8_R8);
2650                                 break;
2651                         case STACK_TYPE_MP:
2652 #if SIZEOF_VOID_P == 4
2653                                 ADD_CODE(td, MINT_CONV_U8_I4);
2654 #endif
2655                                 break;
2656                         default:
2657                                 g_assert_not_reached ();
2658                         }
2659                         ++td->ip;
2660                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I8);
2661                         break;
2662                 case CEE_CPOBJ: {
2663                         CHECK_STACK (td, 2);
2664
2665                         token = read32 (td->ip + 1);
2666                         klass = mono_class_get_full (image, token, generic_context);
2667
2668                         if (klass->valuetype) {
2669                                 ADD_CODE (td, MINT_CPOBJ);
2670                                 ADD_CODE (td, get_data_item_index(td, klass));
2671                         } else {
2672                                 ADD_CODE (td, MINT_LDIND_REF);
2673                                 ADD_CODE (td, MINT_STIND_REF);
2674                         }
2675                         td->ip += 5;
2676                         td->sp -= 2;
2677                         break;
2678                 }
2679                 case CEE_LDOBJ: {
2680                         int size;
2681                         CHECK_STACK (td, 1);
2682
2683                         token = read32 (td->ip + 1);
2684
2685                         if (method->wrapper_type != MONO_WRAPPER_NONE)
2686                                 klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
2687                         else
2688                                 klass = mono_class_get_full (image, token, generic_context);
2689
2690                         ADD_CODE(td, MINT_LDOBJ);
2691                         ADD_CODE(td, get_data_item_index(td, klass));
2692                         if (mint_type (&klass->byval_arg) == MINT_TYPE_VT) {
2693                                 size = mono_class_value_size (klass, NULL);
2694                                 PUSH_VT(td, size);
2695                         }
2696                         td->ip += 5;
2697                         SET_TYPE(td->sp - 1, stack_type[mint_type(&klass->byval_arg)], klass);
2698                         BARRIER_IF_VOLATILE (td);
2699                         break;
2700                 }
2701                 case CEE_LDSTR: {
2702                         MonoString *s;
2703                         token = mono_metadata_token_index (read32 (td->ip + 1));
2704                         td->ip += 5;
2705                         if (method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD) {
2706                                 s = mono_method_get_wrapper_data (method, token);
2707                         } else if (method->wrapper_type != MONO_WRAPPER_NONE) {
2708                                 s = mono_string_new_wrapper (mono_method_get_wrapper_data (method, token));
2709                         } else {
2710                                 s = mono_ldstr (domain, image, token);
2711                         }
2712                         ADD_CODE(td, MINT_LDSTR);
2713                         ADD_CODE(td, get_data_item_index (td, s));
2714                         PUSH_TYPE(td, STACK_TYPE_O, mono_defaults.string_class);
2715                         break;
2716                 }
2717                 case CEE_NEWOBJ: {
2718                         MonoMethod *m;
2719                         MonoMethodSignature *csignature;
2720                         guint32 vt_stack_used = 0;
2721                         guint32 vt_res_size = 0;
2722
2723                         td->ip++;
2724                         token = read32 (td->ip);
2725                         td->ip += 4;
2726
2727                         if (method->wrapper_type != MONO_WRAPPER_NONE)
2728                                 m = (MonoMethod *)mono_method_get_wrapper_data (method, token);
2729                         else 
2730                                 m = mono_get_method_full (image, token, NULL, generic_context);
2731
2732                         csignature = mono_method_signature (m);
2733                         klass = m->klass;
2734
2735                         td->sp -= csignature->param_count;
2736                         if (mono_class_is_magic_int (klass) || mono_class_is_magic_float (klass)) {
2737                                 ADD_CODE (td, MINT_NEWOBJ_MAGIC);
2738                                 ADD_CODE (td, get_data_item_index (td, mono_interp_get_imethod (domain, m, &error)));
2739                                 PUSH_TYPE (td, stack_type [mint_type (&klass->byval_arg)], klass);
2740                         } else {
2741                                 ADD_CODE(td, MINT_NEWOBJ);
2742                                 ADD_CODE(td, get_data_item_index (td, mono_interp_get_imethod (domain, m, &error)));
2743                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
2744
2745                                 if (mint_type (&klass->byval_arg) == MINT_TYPE_VT) {
2746                                         vt_res_size = mono_class_value_size (klass, NULL);
2747                                         PUSH_VT (td, vt_res_size);
2748                                 }
2749                                 for (i = 0; i < csignature->param_count; ++i) {
2750                                         int mt = mint_type(csignature->params [i]);
2751                                         if (mt == MINT_TYPE_VT) {
2752                                                 MonoClass *k = mono_class_from_mono_type (csignature->params [i]);
2753                                                 gint32 size = mono_class_value_size (k, NULL);
2754                                                 size = (size + 7) & ~7;
2755                                                 vt_stack_used += size;
2756                                         }
2757                                 }
2758                                 if (vt_stack_used != 0 || vt_res_size != 0) {
2759                                         ADD_CODE(td, MINT_VTRESULT);
2760                                         ADD_CODE(td, vt_res_size);
2761                                         WRITE32(td, &vt_stack_used);
2762                                         td->vt_sp -= vt_stack_used;
2763                                 }
2764                                 PUSH_TYPE (td, stack_type [mint_type (&klass->byval_arg)], klass);
2765                         }
2766                         break;
2767                 }
2768                 case CEE_CASTCLASS:
2769                         CHECK_STACK (td, 1);
2770                         token = read32 (td->ip + 1);
2771                         klass = mini_get_class (method, token, generic_context);
2772                         ADD_CODE(td, MINT_CASTCLASS);
2773                         ADD_CODE(td, get_data_item_index (td, klass));
2774                         td->sp [-1].klass = klass;
2775                         td->ip += 5;
2776                         break;
2777                 case CEE_ISINST:
2778                         CHECK_STACK (td, 1);
2779                         token = read32 (td->ip + 1);
2780                         klass = mini_get_class (method, token, generic_context);
2781                         ADD_CODE(td, MINT_ISINST);
2782                         ADD_CODE(td, get_data_item_index (td, klass));
2783                         td->ip += 5;
2784                         break;
2785                 case CEE_CONV_R_UN:
2786                         switch (td->sp [-1].type) {
2787                         case STACK_TYPE_R8:
2788                                 break;
2789                         case STACK_TYPE_I8:
2790                                 ADD_CODE(td, MINT_CONV_R_UN_I8);
2791                                 break;
2792                         case STACK_TYPE_I4:
2793                                 ADD_CODE(td, MINT_CONV_R_UN_I4);
2794                                 break;
2795                         default:
2796                                 g_assert_not_reached ();
2797                         }
2798                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_R8);
2799                         ++td->ip;
2800                         break;
2801                 case CEE_UNBOX:
2802                         CHECK_STACK (td, 1);
2803                         token = read32 (td->ip + 1);
2804                         
2805                         if (method->wrapper_type != MONO_WRAPPER_NONE)
2806                                 klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
2807                         else 
2808                                 klass = mono_class_get_full (image, token, generic_context);
2809
2810                         if (mono_class_is_nullable (klass)) {
2811                                 g_error ("cee_unbox: implement Nullable");
2812                         }
2813                         
2814                         ADD_CODE(td, MINT_UNBOX);
2815                         ADD_CODE(td, get_data_item_index (td, klass));
2816                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_MP);
2817                         td->ip += 5;
2818                         break;
2819                 case CEE_UNBOX_ANY:
2820                         CHECK_STACK (td, 1);
2821                         token = read32 (td->ip + 1);
2822
2823                         klass = mini_get_class (method, token, generic_context);
2824
2825                         if (mini_type_is_reference (&klass->byval_arg)) {
2826                                 int mt = mint_type (&klass->byval_arg);
2827                                 ADD_CODE (td, MINT_CASTCLASS);
2828                                 ADD_CODE (td, get_data_item_index (td, klass));
2829                                 SET_TYPE (td->sp - 1, stack_type [mt], klass);
2830                                 td->ip += 5;
2831                         } else if (mono_class_is_nullable (klass)) {
2832                                 MonoMethod *target_method = mono_class_get_method_from_name (klass, "Unbox", 1);
2833                                 /* td->ip is incremented by interp_transform_call */
2834                                 interp_transform_call (td, method, target_method, domain, generic_context, is_bb_start, body_start_offset, NULL, FALSE);
2835                         } else {
2836                                 int mt = mint_type (&klass->byval_arg);
2837                                 ADD_CODE (td, MINT_UNBOX);
2838                                 ADD_CODE (td, get_data_item_index (td, klass));
2839
2840                                 ADD_CODE (td, MINT_LDOBJ);
2841                                 ADD_CODE (td, get_data_item_index(td, klass));
2842                                 SET_TYPE (td->sp - 1, stack_type [mt], klass);
2843
2844                                 if (mt == MINT_TYPE_VT) {
2845                                         int size = mono_class_value_size (klass, NULL);
2846                                         PUSH_VT (td, size);
2847                                 }
2848                                 td->ip += 5;
2849                         }
2850
2851                         break;
2852                 case CEE_THROW:
2853                         CHECK_STACK (td, 1);
2854                         SIMPLE_OP (td, MINT_THROW);
2855                         --td->sp;
2856                         generating_code = 0;
2857                         break;
2858                 case CEE_LDFLDA:
2859                         CHECK_STACK (td, 1);
2860                         token = read32 (td->ip + 1);
2861                         field = interp_field_from_token (method, token, &klass, generic_context);
2862                         gboolean is_static = !!(field->type->attrs & FIELD_ATTRIBUTE_STATIC);
2863                         mono_class_init (klass);
2864                         if (is_static) {
2865                                 ADD_CODE (td, MINT_POP);
2866                                 ADD_CODE (td, 0);
2867                                 ADD_CODE (td, MINT_LDSFLDA);
2868                                 ADD_CODE (td, get_data_item_index (td, field));
2869                         } else {
2870                                 if ((td->sp - 1)->type == STACK_TYPE_O) {
2871                                         ADD_CODE (td, MINT_LDFLDA);
2872                                 } else {
2873                                         g_assert ((td->sp -1)->type == STACK_TYPE_MP);
2874                                         ADD_CODE (td, MINT_LDFLDA_UNSAFE);
2875                                 }
2876                                 ADD_CODE (td, klass->valuetype ? field->offset - sizeof (MonoObject) : field->offset);
2877                         }
2878                         td->ip += 5;
2879                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_MP);
2880                         break;
2881                 case CEE_LDFLD: {
2882                         CHECK_STACK (td, 1);
2883                         token = read32 (td->ip + 1);
2884                         field = interp_field_from_token (method, token, &klass, generic_context);
2885                         gboolean is_static = !!(field->type->attrs & FIELD_ATTRIBUTE_STATIC);
2886                         mono_class_init (klass);
2887
2888                         MonoClass *field_klass = mono_class_from_mono_type (field->type);
2889                         mt = mint_type (&field_klass->byval_arg);
2890 #ifndef DISABLE_REMOTING
2891                         if (klass->marshalbyref) {
2892                                 g_assert (!is_static);
2893                                 ADD_CODE(td, mt == MINT_TYPE_VT ? MINT_LDRMFLD_VT :  MINT_LDRMFLD);
2894                                 ADD_CODE(td, get_data_item_index (td, field));
2895                         } else
2896 #endif
2897                         {
2898                                 if (is_static) {
2899                                         ADD_CODE (td, MINT_POP);
2900                                         ADD_CODE (td, 0);
2901                                         ADD_CODE (td, mt == MINT_TYPE_VT ? MINT_LDSFLD_VT : MINT_LDSFLD);
2902                                         ADD_CODE (td, get_data_item_index (td, field));
2903                                 } else {
2904                                         ADD_CODE (td, MINT_LDFLD_I1 + mt - MINT_TYPE_I1);
2905                                         ADD_CODE (td, klass->valuetype ? field->offset - sizeof(MonoObject) : field->offset);
2906                                 }
2907                         }
2908                         if (mt == MINT_TYPE_VT) {
2909                                 int size = mono_class_value_size (field_klass, NULL);
2910                                 PUSH_VT(td, size);
2911                                 WRITE32(td, &size);
2912                         }
2913                         if (td->sp [-1].type == STACK_TYPE_VT) {
2914                                 int size = mono_class_value_size (klass, NULL);
2915                                 size = (size + 7) & ~7;
2916                                 td->vt_sp -= size;
2917                                 ADD_CODE (td, MINT_VTRESULT);
2918                                 ADD_CODE (td, 0);
2919                                 WRITE32 (td, &size);
2920                         }
2921                         td->ip += 5;
2922                         SET_TYPE(td->sp - 1, stack_type [mt], field_klass);
2923                         BARRIER_IF_VOLATILE (td);
2924                         break;
2925                 }
2926                 case CEE_STFLD: {
2927                         CHECK_STACK (td, 2);
2928                         token = read32 (td->ip + 1);
2929                         field = interp_field_from_token (method, token, &klass, generic_context);
2930                         gboolean is_static = !!(field->type->attrs & FIELD_ATTRIBUTE_STATIC);
2931                         mono_class_init (klass);
2932                         mt = mint_type(field->type);
2933
2934                         BARRIER_IF_VOLATILE (td);
2935
2936 #ifndef DISABLE_REMOTING
2937                         if (klass->marshalbyref) {
2938                                 g_assert (!is_static);
2939                                 ADD_CODE(td, mt == MINT_TYPE_VT ? MINT_STRMFLD_VT : MINT_STRMFLD);
2940                                 ADD_CODE(td, get_data_item_index (td, field));
2941                         } else
2942 #endif
2943                         {
2944                                 if (is_static) {
2945                                         ADD_CODE (td, MINT_POP);
2946                                         ADD_CODE (td, 1);
2947                                         ADD_CODE (td, mt == MINT_TYPE_VT ? MINT_STSFLD_VT : MINT_STSFLD);
2948                                         ADD_CODE (td, get_data_item_index (td, field));
2949                                 } else {
2950                                         ADD_CODE (td, MINT_STFLD_I1 + mt - MINT_TYPE_I1);
2951                                         ADD_CODE (td, klass->valuetype ? field->offset - sizeof(MonoObject) : field->offset);
2952                                 }
2953                         }
2954                         if (mt == MINT_TYPE_VT) {
2955                                 MonoClass *klass = mono_class_from_mono_type (field->type);
2956                                 int size = mono_class_value_size (klass, NULL);
2957                                 POP_VT(td, size);
2958                                 WRITE32(td, &size);
2959                         }
2960                         td->ip += 5;
2961                         td->sp -= 2;
2962                         break;
2963                 }
2964                 case CEE_LDSFLDA:
2965                         token = read32 (td->ip + 1);
2966                         field = interp_field_from_token (method, token, &klass, generic_context);
2967                         ADD_CODE(td, MINT_LDSFLDA);
2968                         ADD_CODE(td, get_data_item_index (td, field));
2969                         td->ip += 5;
2970                         PUSH_SIMPLE_TYPE(td, STACK_TYPE_MP);
2971                         break;
2972                 case CEE_LDSFLD:
2973                         token = read32 (td->ip + 1);
2974                         field = interp_field_from_token (method, token, &klass, generic_context);
2975                         mt = mint_type(field->type);
2976                         ADD_CODE(td, mt == MINT_TYPE_VT ? MINT_LDSFLD_VT : MINT_LDSFLD);
2977                         ADD_CODE(td, get_data_item_index (td, field));
2978                         klass = NULL;
2979                         if (mt == MINT_TYPE_VT) {
2980                                 MonoClass *klass = mono_class_from_mono_type (field->type);
2981                                 int size = mono_class_value_size (klass, NULL);
2982                                 PUSH_VT(td, size);
2983                                 WRITE32(td, &size);
2984                                 klass = field->type->data.klass;
2985                         } else {
2986                                 if (mt == MINT_TYPE_O) 
2987                                         klass = mono_class_from_mono_type (field->type);
2988                         }
2989                         td->ip += 5;
2990                         PUSH_TYPE(td, stack_type [mt], klass);
2991                         break;
2992                 case CEE_STSFLD:
2993                         CHECK_STACK (td, 1);
2994                         token = read32 (td->ip + 1);
2995                         field = interp_field_from_token (method, token, &klass, generic_context);
2996                         mt = mint_type(field->type);
2997                         ADD_CODE(td, mt == MINT_TYPE_VT ? MINT_STSFLD_VT : MINT_STSFLD);
2998                         ADD_CODE(td, get_data_item_index (td, field));
2999                         if (mt == MINT_TYPE_VT) {
3000                                 MonoClass *klass = mono_class_from_mono_type (field->type);
3001                                 int size = mono_class_value_size (klass, NULL);
3002                                 POP_VT (td, size);
3003                                 WRITE32 (td, &size);
3004                         }
3005                         td->ip += 5;
3006                         --td->sp;
3007                         break;
3008                 case CEE_STOBJ: {
3009                         int size;
3010                         token = read32 (td->ip + 1);
3011
3012                         if (method->wrapper_type != MONO_WRAPPER_NONE)
3013                                 klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
3014                         else
3015                                 klass = mini_get_class (method, token, generic_context);
3016
3017                         BARRIER_IF_VOLATILE (td);
3018                         ADD_CODE(td, td->sp [-1].type == STACK_TYPE_VT ? MINT_STOBJ_VT : MINT_STOBJ);
3019                         ADD_CODE(td, get_data_item_index (td, klass));
3020                         if (td->sp [-1].type == STACK_TYPE_VT) {
3021                                 size = mono_class_value_size (klass, NULL);
3022                                 size = (size + 7) & ~7;
3023                                 td->vt_sp -= size;
3024                         }
3025                         td->ip += 5;
3026                         td->sp -= 2;
3027                         break;
3028                 }
3029                 case CEE_CONV_OVF_I_UN:
3030                 case CEE_CONV_OVF_U_UN:
3031                         CHECK_STACK (td, 1);
3032                         switch (td->sp [-1].type) {
3033                         case STACK_TYPE_R8:
3034 #if SIZEOF_VOID_P == 8
3035                                 ADD_CODE(td, MINT_CONV_OVF_I8_UN_R8);
3036 #else
3037                                 ADD_CODE(td, MINT_CONV_OVF_I4_UN_R8);
3038 #endif
3039                                 break;
3040                         case STACK_TYPE_I8:
3041 #if SIZEOF_VOID_P == 4
3042                                 ADD_CODE (td, MINT_CONV_OVF_I4_UN_I8);
3043 #endif
3044                                 break;
3045                         case STACK_TYPE_I4:
3046 #if SIZEOF_VOID_P == 8
3047                                 ADD_CODE(td, MINT_CONV_I8_U4);
3048 #elif SIZEOF_VOID_P == 4
3049                                 if (*td->ip == CEE_CONV_OVF_I_UN)
3050                                         ADD_CODE(td, MINT_CONV_OVF_I4_U4);
3051 #endif
3052                                 break;
3053                         default:
3054                                 g_assert_not_reached ();
3055                                 break;
3056                         }
3057                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I8);
3058                         ++td->ip;
3059                         break;
3060                 case CEE_CONV_OVF_I8_UN:
3061                 case CEE_CONV_OVF_U8_UN:
3062                         CHECK_STACK (td, 1);
3063                         switch (td->sp [-1].type) {
3064                         case STACK_TYPE_R8:
3065                                 ADD_CODE(td, MINT_CONV_OVF_I8_UN_R8);
3066                                 break;
3067                         case STACK_TYPE_I8:
3068                                 if (*td->ip == CEE_CONV_OVF_I8_UN)
3069                                         ADD_CODE (td, MINT_CONV_OVF_I8_U8);
3070                                 break;
3071                         case STACK_TYPE_I4:
3072                                 ADD_CODE(td, MINT_CONV_I8_U4);
3073                                 break;
3074                         default:
3075                                 g_assert_not_reached ();
3076                                 break;
3077                         }
3078                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I8);
3079                         ++td->ip;
3080                         break;
3081                 case CEE_BOX: {
3082                         int size;
3083                         CHECK_STACK (td, 1);
3084                         token = read32 (td->ip + 1);
3085                         if (method->wrapper_type != MONO_WRAPPER_NONE)
3086                                 klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
3087                         else
3088                                 klass = mini_get_class (method, token, generic_context);
3089
3090                         if (mono_class_is_nullable (klass)) {
3091                                 MonoMethod *target_method = mono_class_get_method_from_name (klass, "Box", 1);
3092                                 /* td->ip is incremented by interp_transform_call */
3093                                 interp_transform_call (td, method, target_method, domain, generic_context, is_bb_start, body_start_offset, NULL, FALSE);
3094                         } else if (!klass->valuetype) {
3095                                 /* already boxed, do nothing. */
3096                                 td->ip += 5;
3097                         } else {
3098                                 if (mint_type (&klass->byval_arg) == MINT_TYPE_VT && !klass->enumtype) {
3099                                         size = mono_class_value_size (klass, NULL);
3100                                         size = (size + 7) & ~7;
3101                                         td->vt_sp -= size;
3102                                 }
3103                                 ADD_CODE(td, MINT_BOX);
3104                                 ADD_CODE(td, get_data_item_index (td, klass));
3105                                 ADD_CODE (td, 0);
3106                                 SET_TYPE(td->sp - 1, STACK_TYPE_O, klass);
3107                                 td->ip += 5;
3108                         }
3109
3110                         break;
3111                 }
3112                 case CEE_NEWARR: {
3113                         CHECK_STACK (td, 1);
3114                         token = read32 (td->ip + 1);
3115
3116                         if (method->wrapper_type != MONO_WRAPPER_NONE)
3117                                 klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
3118                         else
3119                                 klass = mini_get_class (method, token, generic_context);
3120
3121                         unsigned char lentype = (td->sp - 1)->type;
3122                         if (lentype == STACK_TYPE_I8) {
3123                                 /* mimic mini behaviour */
3124                                 ADD_CODE (td, MINT_CONV_OVF_U4_I8);
3125                         } else {
3126                                 g_assert (lentype == STACK_TYPE_I4);
3127                                 ADD_CODE (td, MINT_CONV_OVF_U4_I4);
3128                         }
3129                         SET_SIMPLE_TYPE (td->sp - 1, STACK_TYPE_I4);
3130                         ADD_CODE (td, MINT_NEWARR);
3131                         ADD_CODE (td, get_data_item_index (td, klass));
3132                         SET_TYPE (td->sp - 1, STACK_TYPE_O, klass);
3133                         td->ip += 5;
3134                         break;
3135                 }
3136                 case CEE_LDLEN:
3137                         CHECK_STACK (td, 1);
3138                         SIMPLE_OP (td, MINT_LDLEN);
3139                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I);
3140                         break;
3141                 case CEE_LDELEMA:
3142                         CHECK_STACK (td, 2);
3143                         ENSURE_I4 (td, 1);
3144                         token = read32 (td->ip + 1);
3145
3146                         if (method->wrapper_type != MONO_WRAPPER_NONE)
3147                                 klass = (MonoClass *) mono_method_get_wrapper_data (method, token);
3148                         else
3149                                 klass = mini_get_class (method, token, generic_context);
3150
3151                         if (!klass->valuetype && method->wrapper_type == MONO_WRAPPER_NONE && !readonly) {
3152                                 ADD_CODE (td, MINT_LDELEMA_TC);
3153                         } else {
3154                                 ADD_CODE (td, MINT_LDELEMA);
3155                         }
3156                         ADD_CODE (td, get_data_item_index (td, klass));
3157                         /* according to spec, ldelema bytecode is only used for 1-dim arrays */
3158                         ADD_CODE (td, 2);
3159                         readonly = FALSE;
3160
3161                         td->ip += 5;
3162                         --td->sp;
3163                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_MP);
3164                         break;
3165                 case CEE_LDELEM_I1:
3166                         CHECK_STACK (td, 2);
3167                         ENSURE_I4 (td, 1);
3168                         SIMPLE_OP (td, MINT_LDELEM_I1);
3169                         --td->sp;
3170                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
3171                         break;
3172                 case CEE_LDELEM_U1:
3173                         CHECK_STACK (td, 2);
3174                         ENSURE_I4 (td, 1);
3175                         SIMPLE_OP (td, MINT_LDELEM_U1);
3176                         --td->sp;
3177                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
3178                         break;
3179                 case CEE_LDELEM_I2:
3180                         CHECK_STACK (td, 2);
3181                         ENSURE_I4 (td, 1);
3182                         SIMPLE_OP (td, MINT_LDELEM_I2);
3183                         --td->sp;
3184                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
3185                         break;
3186                 case CEE_LDELEM_U2:
3187                         CHECK_STACK (td, 2);
3188                         ENSURE_I4 (td, 1);
3189                         SIMPLE_OP (td, MINT_LDELEM_U2);
3190                         --td->sp;
3191                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
3192                         break;
3193                 case CEE_LDELEM_I4:
3194                         CHECK_STACK (td, 2);
3195                         ENSURE_I4 (td, 1);
3196                         SIMPLE_OP (td, MINT_LDELEM_I4);
3197                         --td->sp;
3198                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
3199                         break;
3200                 case CEE_LDELEM_U4:
3201                         CHECK_STACK (td, 2);
3202                         ENSURE_I4 (td, 1);
3203                         SIMPLE_OP (td, MINT_LDELEM_U4);
3204                         --td->sp;
3205                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
3206                         break;
3207                 case CEE_LDELEM_I8:
3208                         CHECK_STACK (td, 2);
3209                         ENSURE_I4 (td, 1);
3210                         SIMPLE_OP (td, MINT_LDELEM_I8);
3211                         --td->sp;
3212                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I8);
3213                         break;
3214                 case CEE_LDELEM_I:
3215                         CHECK_STACK (td, 2);
3216                         ENSURE_I4 (td, 1);
3217                         SIMPLE_OP (td, MINT_LDELEM_I);
3218                         --td->sp;
3219                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I);
3220                         break;
3221                 case CEE_LDELEM_R4:
3222                         CHECK_STACK (td, 2);
3223                         ENSURE_I4 (td, 1);
3224                         SIMPLE_OP (td, MINT_LDELEM_R4);
3225                         --td->sp;
3226                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_R8);
3227                         break;
3228                 case CEE_LDELEM_R8:
3229                         CHECK_STACK (td, 2);
3230                         ENSURE_I4 (td, 1);
3231                         SIMPLE_OP (td, MINT_LDELEM_R8);
3232                         --td->sp;
3233                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_R8);
3234                         break;
3235                 case CEE_LDELEM_REF:
3236                         CHECK_STACK (td, 2);
3237                         ENSURE_I4 (td, 1);
3238                         SIMPLE_OP (td, MINT_LDELEM_REF);
3239                         --td->sp;
3240                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_O);
3241                         break;
3242                 case CEE_LDELEM:
3243                         CHECK_STACK (td, 2);
3244                         token = read32 (td->ip + 1);
3245                         klass = mini_get_class (method, token, generic_context);
3246                         switch (mint_type (&klass->byval_arg)) {
3247                                 case MINT_TYPE_I1:
3248                                         ENSURE_I4 (td, 1);
3249                                         SIMPLE_OP (td, MINT_LDELEM_I1);
3250                                         --td->sp;
3251                                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
3252                                         break;
3253                                 case MINT_TYPE_U1:
3254                                         ENSURE_I4 (td, 1);
3255                                         SIMPLE_OP (td, MINT_LDELEM_U1);
3256                                         --td->sp;
3257                                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
3258                                         break;
3259                                 case MINT_TYPE_U2:
3260                                         ENSURE_I4 (td, 1);
3261                                         SIMPLE_OP (td, MINT_LDELEM_U2);
3262                                         --td->sp;
3263                                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
3264                                         break;
3265                                 case MINT_TYPE_I2:
3266                                         ENSURE_I4 (td, 1);
3267                                         SIMPLE_OP (td, MINT_LDELEM_I2);
3268                                         --td->sp;
3269                                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
3270                                         break;
3271                                 case MINT_TYPE_I4:
3272                                         ENSURE_I4 (td, 1);
3273                                         SIMPLE_OP (td, MINT_LDELEM_I4);
3274                                         --td->sp;
3275                                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
3276                                         break;
3277                                 case MINT_TYPE_I8:
3278                                         ENSURE_I4 (td, 1);
3279                                         SIMPLE_OP (td, MINT_LDELEM_I8);
3280                                         --td->sp;
3281                                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I8);
3282                                         break;
3283                                 case MINT_TYPE_R4:
3284                                         ENSURE_I4 (td, 1);
3285                                         SIMPLE_OP (td, MINT_LDELEM_R4);
3286                                         --td->sp;
3287                                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_R8);
3288                                         break;
3289                                 case MINT_TYPE_R8:
3290                                         ENSURE_I4 (td, 1);
3291                                         SIMPLE_OP (td, MINT_LDELEM_R8);
3292                                         --td->sp;
3293                                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_R8);
3294                                         break;
3295                                 case MINT_TYPE_O:
3296                                         ENSURE_I4 (td, 1);
3297                                         SIMPLE_OP (td, MINT_LDELEM_REF);
3298                                         --td->sp;
3299                                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_O);
3300                                         break;
3301                                 case MINT_TYPE_VT: {
3302                                         int size = mono_class_value_size (klass, NULL);
3303                                         ENSURE_I4 (td, 1);
3304                                         SIMPLE_OP (td, MINT_LDELEM_VT);
3305                                         ADD_CODE (td, get_data_item_index (td, klass));
3306                                         WRITE32 (td, &size);
3307                                         --td->sp;
3308                                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_VT);
3309                                         PUSH_VT (td, size);
3310                                         break;
3311                                 }
3312                                 default: {
3313                                         GString *res = g_string_new ("");
3314                                         mono_type_get_desc (res, &klass->byval_arg, TRUE);
3315                                         g_print ("LDELEM: %s -> %d (%s)\n", klass->name, mint_type (&klass->byval_arg), res->str);
3316                                         g_string_free (res, TRUE);
3317                                         g_assert (0);
3318                                         break;
3319                                 }
3320                         }
3321                         td->ip += 4;
3322                         break;
3323                 case CEE_STELEM_I:
3324                         CHECK_STACK (td, 3);
3325                         ENSURE_I4 (td, 2);
3326                         SIMPLE_OP (td, MINT_STELEM_I);
3327                         td->sp -= 3;
3328                         break;
3329                 case CEE_STELEM_I1:
3330                         CHECK_STACK (td, 3);
3331                         ENSURE_I4 (td, 2);
3332                         SIMPLE_OP (td, MINT_STELEM_I1);
3333                         td->sp -= 3;
3334                         break;
3335                 case CEE_STELEM_I2:
3336                         CHECK_STACK (td, 3);
3337                         ENSURE_I4 (td, 2);
3338                         SIMPLE_OP (td, MINT_STELEM_I2);
3339                         td->sp -= 3;
3340                         break;
3341                 case CEE_STELEM_I4:
3342                         CHECK_STACK (td, 3);
3343                         ENSURE_I4 (td, 2);
3344                         SIMPLE_OP (td, MINT_STELEM_I4);
3345                         td->sp -= 3;
3346                         break;
3347                 case CEE_STELEM_I8:
3348                         CHECK_STACK (td, 3);
3349                         ENSURE_I4 (td, 2);
3350                         SIMPLE_OP (td, MINT_STELEM_I8);
3351                         td->sp -= 3;
3352                         break;
3353                 case CEE_STELEM_R4:
3354                         CHECK_STACK (td, 3);
3355                         ENSURE_I4 (td, 2);
3356                         SIMPLE_OP (td, MINT_STELEM_R4);
3357                         td->sp -= 3;
3358                         break;
3359                 case CEE_STELEM_R8:
3360                         CHECK_STACK (td, 3);
3361                         ENSURE_I4 (td, 2);
3362                         SIMPLE_OP (td, MINT_STELEM_R8);
3363                         td->sp -= 3;
3364                         break;
3365                 case CEE_STELEM_REF:
3366                         CHECK_STACK (td, 3);
3367                         ENSURE_I4 (td, 2);
3368                         SIMPLE_OP (td, MINT_STELEM_REF);
3369                         td->sp -= 3;
3370                         break;
3371                 case CEE_STELEM:
3372                         CHECK_STACK (td, 3);
3373                         ENSURE_I4 (td, 2);
3374                         token = read32 (td->ip + 1);
3375                         klass = mini_get_class (method, token, generic_context);
3376                         switch (mint_type (&klass->byval_arg)) {
3377                                 case MINT_TYPE_U1:
3378                                         SIMPLE_OP (td, MINT_STELEM_U1);
3379                                         break;
3380                                 case MINT_TYPE_U2:
3381                                         SIMPLE_OP (td, MINT_STELEM_U2);
3382                                         break;
3383                                 case MINT_TYPE_I4:
3384                                         SIMPLE_OP (td, MINT_STELEM_I4);
3385                                         break;
3386                                 case MINT_TYPE_I8:
3387                                         SIMPLE_OP (td, MINT_STELEM_I8);
3388                                         break;
3389                                 case MINT_TYPE_O:
3390                                         SIMPLE_OP (td, MINT_STELEM_REF);
3391                                         break;
3392                                 case MINT_TYPE_VT: {
3393                                         int size = mono_class_value_size (klass, NULL);
3394                                         SIMPLE_OP (td, MINT_STELEM_VT);
3395                                         ADD_CODE (td, get_data_item_index (td, klass));
3396                                         WRITE32 (td, &size);
3397                                         POP_VT (td, size);
3398                                         break;
3399                                 }
3400                                 default: {
3401                                         GString *res = g_string_new ("");
3402                                         mono_type_get_desc (res, &klass->byval_arg, TRUE);
3403                                         g_print ("STELEM: %s -> %d (%s)\n", klass->name, mint_type (&klass->byval_arg), res->str);
3404                                         g_string_free (res, TRUE);
3405                                         g_assert (0);
3406                                         break;
3407                                 }
3408                         }
3409                         td->ip += 4;
3410                         td->sp -= 3;
3411                         break;
3412 #if 0
3413                 case CEE_CONV_OVF_U1:
3414
3415                 case CEE_CONV_OVF_I8:
3416
3417 #if SIZEOF_VOID_P == 8
3418                 case CEE_CONV_OVF_U:
3419 #endif
3420 #endif
3421                 case CEE_CKFINITE:
3422                         CHECK_STACK (td, 1);
3423                         SIMPLE_OP (td, MINT_CKFINITE);
3424                         break;
3425                 case CEE_MKREFANY:
3426                         CHECK_STACK (td, 1);
3427                         ENSURE_I4 (td, 2);
3428                         token = read32 (td->ip + 1);
3429                         klass = mini_get_class (method, token, generic_context);
3430
3431                         ADD_CODE (td, MINT_MKREFANY);
3432                         ADD_CODE (td, get_data_item_index (td, klass));
3433
3434                         td->ip += 5;
3435                         PUSH_VT (td, sizeof (MonoTypedRef));
3436                         SET_TYPE(td->sp - 1, STACK_TYPE_VT, mono_defaults.typed_reference_class);
3437                         break;
3438                 case CEE_REFANYVAL: {
3439                         CHECK_STACK (td, 1);
3440                         ENSURE_I4 (td, 2);
3441                         token = read32 (td->ip + 1);
3442
3443                         ADD_CODE (td, MINT_REFANYVAL);
3444
3445                         POP_VT (td, sizeof (MonoTypedRef));
3446                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_MP);
3447
3448                         td->ip += 5;
3449                         break;
3450                 }
3451                 case CEE_CONV_OVF_I1:
3452                 case CEE_CONV_OVF_I1_UN:
3453                         CHECK_STACK (td, 1);
3454                         switch (td->sp [-1].type) {
3455                         case STACK_TYPE_R8:
3456                                 ADD_CODE(td, MINT_CONV_OVF_I1_R8);
3457                                 break;
3458                         case STACK_TYPE_I4:
3459                                 ADD_CODE(td, MINT_CONV_OVF_I1_I4);
3460                                 break;
3461                         case STACK_TYPE_I8:
3462                                 ADD_CODE(td, MINT_CONV_OVF_I1_I8);
3463                                 break;
3464                         default:
3465                                 g_assert_not_reached ();
3466                         }
3467                         ++td->ip;
3468                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
3469                         break;
3470                 case CEE_CONV_OVF_U1:
3471                 case CEE_CONV_OVF_U1_UN:
3472                         CHECK_STACK (td, 1);
3473                         switch (td->sp [-1].type) {
3474                         case STACK_TYPE_R8:
3475                                 ADD_CODE(td, MINT_CONV_OVF_U1_R8);
3476                                 break;
3477                         case STACK_TYPE_I4:
3478                                 ADD_CODE(td, MINT_CONV_OVF_U1_I4);
3479                                 break;
3480                         case STACK_TYPE_I8:
3481                                 ADD_CODE(td, MINT_CONV_OVF_U1_I8);
3482                                 break;
3483                         default:
3484                                 g_assert_not_reached ();
3485                         }
3486                         ++td->ip;
3487                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
3488                         break;
3489                 case CEE_CONV_OVF_I2:
3490                 case CEE_CONV_OVF_I2_UN:
3491                         CHECK_STACK (td, 1);
3492                         switch (td->sp [-1].type) {
3493                         case STACK_TYPE_R8:
3494                                 ADD_CODE(td, MINT_CONV_OVF_I2_R8);
3495                                 break;
3496                         case STACK_TYPE_I4:
3497                                 ADD_CODE(td, MINT_CONV_OVF_I2_I4);
3498                                 break;
3499                         case STACK_TYPE_I8:
3500                                 ADD_CODE(td, MINT_CONV_OVF_I2_I8);
3501                                 break;
3502                         default:
3503                                 g_assert_not_reached ();
3504                         }
3505                         ++td->ip;
3506                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
3507                         break;
3508                 case CEE_CONV_OVF_U2_UN:
3509                 case CEE_CONV_OVF_U2:
3510                         CHECK_STACK (td, 1);
3511                         switch (td->sp [-1].type) {
3512                         case STACK_TYPE_R8:
3513                                 ADD_CODE(td, MINT_CONV_OVF_U2_R8);
3514                                 break;
3515                         case STACK_TYPE_I4:
3516                                 ADD_CODE(td, MINT_CONV_OVF_U2_I4);
3517                                 break;
3518                         case STACK_TYPE_I8:
3519                                 ADD_CODE(td, MINT_CONV_OVF_U2_I8);
3520                                 break;
3521                         default:
3522                                 g_assert_not_reached ();
3523                         }
3524                         ++td->ip;
3525                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
3526                         break;
3527 #if SIZEOF_VOID_P == 4
3528                 case CEE_CONV_OVF_I:
3529 #endif
3530                 case CEE_CONV_OVF_I4:
3531                 case CEE_CONV_OVF_I4_UN:
3532                         CHECK_STACK (td, 1);
3533                         switch (td->sp [-1].type) {
3534                         case STACK_TYPE_R8:
3535                                 ADD_CODE(td, MINT_CONV_OVF_I4_R8);
3536                                 break;
3537                         case STACK_TYPE_I4:
3538                                 if (*td->ip == CEE_CONV_OVF_I4_UN)
3539                                         ADD_CODE(td, MINT_CONV_OVF_I4_U4);
3540                                 break;
3541                         case STACK_TYPE_I8:
3542                                 if (*td->ip == CEE_CONV_OVF_I4_UN)
3543                                         ADD_CODE (td, MINT_CONV_OVF_I4_U8);
3544                                 else
3545                                         ADD_CODE (td, MINT_CONV_OVF_I4_I8);
3546                                 break;
3547                         default:
3548                                 g_assert_not_reached ();
3549                         }
3550                         ++td->ip;
3551                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
3552                         break;
3553 #if SIZEOF_VOID_P == 4
3554                 case CEE_CONV_OVF_U:
3555 #endif
3556                 case CEE_CONV_OVF_U4:
3557                 case CEE_CONV_OVF_U4_UN:
3558                         CHECK_STACK (td, 1);
3559                         switch (td->sp [-1].type) {
3560                         case STACK_TYPE_R8:
3561                                 ADD_CODE(td, MINT_CONV_OVF_U4_R8);
3562                                 break;
3563                         case STACK_TYPE_I4:
3564                                 if (*td->ip != CEE_CONV_OVF_U4_UN)
3565                                         ADD_CODE(td, MINT_CONV_OVF_U4_I4);
3566                                 break;
3567                         case STACK_TYPE_I8:
3568                                 ADD_CODE(td, MINT_CONV_OVF_U4_I8);
3569                                 break;
3570                         default:
3571                                 g_assert_not_reached ();
3572                         }
3573                         ++td->ip;
3574                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
3575                         break;
3576 #if SIZEOF_VOID_P == 8
3577                 case CEE_CONV_OVF_I:
3578 #endif
3579                 case CEE_CONV_OVF_I8:
3580                         CHECK_STACK (td, 1);
3581                         switch (td->sp [-1].type) {
3582                         case STACK_TYPE_R8:
3583                                 ADD_CODE(td, MINT_CONV_OVF_I8_R8);
3584                                 break;
3585                         case STACK_TYPE_I4:
3586                                 ADD_CODE(td, MINT_CONV_I8_I4);
3587                                 break;
3588                         case STACK_TYPE_I8:
3589                                 break;
3590                         default:
3591                                 g_assert_not_reached ();
3592                         }
3593                         ++td->ip;
3594                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I8);
3595                         break;
3596 #if SIZEOF_VOID_P == 8
3597                 case CEE_CONV_OVF_U:
3598 #endif
3599                 case CEE_CONV_OVF_U8:
3600                         CHECK_STACK (td, 1);
3601                         switch (td->sp [-1].type) {
3602                         case STACK_TYPE_R8:
3603                                 ADD_CODE(td, MINT_CONV_OVF_U8_R8);
3604                                 break;
3605                         case STACK_TYPE_I4:
3606                                 ADD_CODE(td, MINT_CONV_OVF_U8_I4);
3607                                 break;
3608                         case STACK_TYPE_I8:
3609                                 ADD_CODE (td, MINT_CONV_OVF_U8_I8);
3610                                 break;
3611                         default:
3612                                 g_assert_not_reached ();
3613                         }
3614                         ++td->ip;
3615                         SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I8);
3616                         break;
3617                 case CEE_LDTOKEN: {
3618                         int size;
3619                         gpointer handle;
3620                         token = read32 (td->ip + 1);
3621                         if (method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD || method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED) {
3622                                 handle = mono_method_get_wrapper_data (method, token);
3623                                 klass = (MonoClass *) mono_method_get_wrapper_data (method, token + 1);
3624                                 if (klass == mono_defaults.typehandle_class)
3625                                         handle = &((MonoClass *) handle)->byval_arg;
3626
3627                                 if (generic_context) {
3628                                         handle = mono_class_inflate_generic_type_checked (handle, generic_context, &error);
3629                                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3630                                 }
3631                         } else {
3632                                 handle = mono_ldtoken (image, token, &klass, generic_context);
3633                         }
3634                         mono_class_init (klass);
3635                         mt = mint_type (&klass->byval_arg);
3636                         g_assert (mt == MINT_TYPE_VT);
3637                         size = mono_class_value_size (klass, NULL);
3638                         g_assert (size == sizeof(gpointer));
3639                         PUSH_VT (td, sizeof(gpointer));
3640                         ADD_CODE (td, MINT_LDTOKEN);
3641                         ADD_CODE (td, get_data_item_index (td, handle));
3642
3643                         SET_TYPE (td->sp, stack_type [mt], klass);
3644                         td->sp++;
3645                         td->ip += 5;
3646                         break;
3647                 }
3648                 case CEE_ADD_OVF:
3649                         binary_arith_op(td, MINT_ADD_OVF_I4);
3650                         ++td->ip;
3651                         break;
3652                 case CEE_ADD_OVF_UN:
3653                         binary_arith_op(td, MINT_ADD_OVF_UN_I4);
3654                         ++td->ip;
3655                         break;
3656                 case CEE_MUL_OVF:
3657                         binary_arith_op(td, MINT_MUL_OVF_I4);
3658                         ++td->ip;
3659                         break;
3660                 case CEE_MUL_OVF_UN:
3661                         binary_arith_op(td, MINT_MUL_OVF_UN_I4);
3662                         ++td->ip;
3663                         break;
3664                 case CEE_SUB_OVF:
3665                         binary_arith_op(td, MINT_SUB_OVF_I4);
3666                         ++td->ip;
3667                         break;
3668                 case CEE_SUB_OVF_UN:
3669                         binary_arith_op(td, MINT_SUB_OVF_UN_I4);
3670                         ++td->ip;
3671                         break;
3672                 case CEE_ENDFINALLY:
3673                         g_assert (td->clause_indexes [in_offset] != -1);
3674                         td->sp = td->stack;
3675                         SIMPLE_OP (td, MINT_ENDFINALLY);
3676                         ADD_CODE (td, td->clause_indexes [in_offset]);
3677                         generating_code = 0;
3678                         break;
3679                 case CEE_LEAVE:
3680                         td->sp = td->stack;
3681                         handle_branch (td, MINT_LEAVE_S, MINT_LEAVE, 5 + read32 (td->ip + 1));
3682                         td->ip += 5;
3683                         generating_code = 0;
3684                         break;
3685                 case CEE_LEAVE_S:
3686                         td->sp = td->stack;
3687                         handle_branch (td, MINT_LEAVE_S, MINT_LEAVE, 2 + (gint8)td->ip [1]);
3688                         td->ip += 2;
3689                         generating_code = 0;
3690                         break;
3691                 case CEE_UNUSED41:
3692                         ++td->ip;
3693                         switch (*td->ip) {
3694                                 case CEE_MONO_CALLI_EXTRA_ARG:
3695                                         /* Same as CEE_CALLI, except that we drop the extra arg required for llvm specific behaviour */
3696                                         ADD_CODE (td, MINT_POP);
3697                                         ADD_CODE (td, 1);
3698                                         --td->sp;
3699                                         interp_transform_call (td, method, NULL, domain, generic_context, is_bb_start, body_start_offset, NULL, FALSE);
3700                                         break;
3701                                 case CEE_MONO_JIT_ICALL_ADDR: {
3702                                         guint32 token;
3703                                         gpointer func;
3704                                         MonoJitICallInfo *info;
3705
3706                                         token = read32 (td->ip + 1);
3707                                         td->ip += 5;
3708                                         func = mono_method_get_wrapper_data (method, token);
3709                                         info = mono_find_jit_icall_by_addr (func);
3710
3711                                         ADD_CODE (td, MINT_LDFTN);
3712                                         ADD_CODE (td, get_data_item_index (td, func));
3713                                         PUSH_SIMPLE_TYPE (td, STACK_TYPE_I);
3714                                         break;
3715                                 }
3716                                 case CEE_MONO_ICALL: {
3717                                         guint32 token;
3718                                         gpointer func;
3719                                         MonoJitICallInfo *info;
3720
3721                                         token = read32 (td->ip + 1);
3722                                         td->ip += 5;
3723                                         func = mono_method_get_wrapper_data (method, token);
3724                                         info = mono_find_jit_icall_by_addr (func);
3725                                         g_assert (info);
3726
3727                                         CHECK_STACK (td, info->sig->param_count);
3728                                         switch (info->sig->param_count) {
3729                                         case 0:
3730                                                 if (MONO_TYPE_IS_VOID (info->sig->ret))
3731                                                         ADD_CODE (td,MINT_ICALL_V_V);
3732                                                 else
3733                                                         ADD_CODE (td, MINT_ICALL_V_P);
3734                                                 break;
3735                                         case 1:
3736                                                 if (MONO_TYPE_IS_VOID (info->sig->ret))
3737                                                         ADD_CODE (td,MINT_ICALL_P_V);
3738                                                 else
3739                                                         ADD_CODE (td,MINT_ICALL_P_P);
3740                                                 break;
3741                                         case 2:
3742                                                 if (MONO_TYPE_IS_VOID (info->sig->ret)) {
3743                                                         if (info->sig->params [1]->type == MONO_TYPE_I4)
3744                                                                 ADD_CODE (td,MINT_ICALL_PI_V);
3745                                                         else
3746                                                                 ADD_CODE (td,MINT_ICALL_PP_V);
3747                                                 } else {
3748                                                         if (info->sig->params [1]->type == MONO_TYPE_I4)
3749                                                                 ADD_CODE (td,MINT_ICALL_PI_P);
3750                                                         else
3751                                                                 ADD_CODE (td,MINT_ICALL_PP_P);
3752                                                 }
3753                                                 break;
3754                                         case 3:
3755                                                 g_assert (MONO_TYPE_IS_VOID (info->sig->ret));
3756                                                 if (info->sig->params [2]->type == MONO_TYPE_I4)
3757                                                         ADD_CODE (td,MINT_ICALL_PPI_V);
3758                                                 else
3759                                                         ADD_CODE (td,MINT_ICALL_PPP_V);
3760                                                 break;
3761                                         default:
3762                                                 g_assert_not_reached ();
3763                                         }
3764
3765                                         if (func == mono_ftnptr_to_delegate) {
3766                                                 g_error ("TODO: ?");
3767                                         }
3768                                         ADD_CODE(td, get_data_item_index (td, func));
3769                                         td->sp -= info->sig->param_count;
3770
3771                                         if (!MONO_TYPE_IS_VOID (info->sig->ret)) {
3772                                                 td->sp ++;
3773                                                 SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I);
3774                                         }
3775                                         break;
3776                                 }
3777                         case CEE_MONO_VTADDR: {
3778                                 int size;
3779                                 CHECK_STACK (td, 1);
3780                                 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
3781                                         size = mono_class_native_size(td->sp [-1].klass, NULL);
3782                                 else
3783                                         size = mono_class_value_size(td->sp [-1].klass, NULL);
3784                                 size = (size + 7) & ~7;
3785                                 ADD_CODE(td, MINT_VTRESULT);
3786                                 ADD_CODE(td, 0);
3787                                 WRITE32(td, &size);
3788                                 td->vt_sp -= size;
3789                                 ++td->ip;
3790                                 SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_MP);
3791                                 break;
3792                         }
3793                         case CEE_MONO_LDPTR:
3794                         case CEE_MONO_CLASSCONST:
3795                                 token = read32 (td->ip + 1);
3796                                 td->ip += 5;
3797                                 ADD_CODE(td, MINT_MONO_LDPTR);
3798                                 ADD_CODE(td, get_data_item_index (td, mono_method_get_wrapper_data (method, token)));
3799                                 td->sp [0].type = STACK_TYPE_I;
3800                                 ++td->sp;
3801                                 break;
3802                         case CEE_MONO_OBJADDR:
3803                                 CHECK_STACK (td, 1);
3804                                 ++td->ip;
3805                                 td->sp[-1].type = STACK_TYPE_MP;
3806                                 /* do nothing? */
3807                                 break;
3808                         case CEE_MONO_NEWOBJ:
3809                                 token = read32 (td->ip + 1);
3810                                 td->ip += 5;
3811                                 ADD_CODE(td, MINT_MONO_NEWOBJ);
3812                                 ADD_CODE(td, get_data_item_index (td, mono_method_get_wrapper_data (method, token)));
3813                                 td->sp [0].type = STACK_TYPE_O;
3814                                 ++td->sp;
3815                                 break;
3816                         case CEE_MONO_RETOBJ:
3817                                 CHECK_STACK (td, 1);
3818                                 token = read32 (td->ip + 1);
3819                                 td->ip += 5;
3820                                 ADD_CODE(td, MINT_MONO_RETOBJ);
3821                                 td->sp--;
3822
3823                                 klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
3824                                 
3825                                 /*stackval_from_data (signature->ret, frame->retval, sp->data.vt, signature->pinvoke);*/
3826
3827                                 if (td->sp > td->stack)
3828                                         g_warning ("CEE_MONO_RETOBJ: more values on stack: %d", td->sp-td->stack);
3829                                 break;
3830                         case CEE_MONO_LDNATIVEOBJ:
3831                                 token = read32 (td->ip + 1);
3832                                 td->ip += 5;
3833                                 klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
3834                                 g_assert(klass->valuetype);
3835                                 SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_MP);
3836                                 break;
3837                         case CEE_MONO_TLS: {
3838                                 gint32 key = read32 (td->ip + 1);
3839                                 td->ip += 5;
3840                                 g_assert (key < TLS_KEY_NUM);
3841                                 ADD_CODE (td, MINT_MONO_TLS);
3842                                 WRITE32 (td, &key);
3843                                 PUSH_SIMPLE_TYPE (td, STACK_TYPE_MP);
3844                                 break;
3845                         }
3846                         case CEE_MONO_ATOMIC_STORE_I4:
3847                                 CHECK_STACK (td, 2);
3848                                 SIMPLE_OP (td, MINT_MONO_ATOMIC_STORE_I4);
3849                                 td->sp -= 2;
3850                                 td->ip++;
3851                                 break;
3852                         case CEE_MONO_SAVE_LMF:
3853                         case CEE_MONO_RESTORE_LMF:
3854                         case CEE_MONO_NOT_TAKEN:
3855                                 ++td->ip;
3856                                 break;
3857                         case CEE_MONO_LDPTR_INT_REQ_FLAG:
3858                                 ADD_CODE (td, MINT_MONO_LDPTR);
3859                                 ADD_CODE (td, get_data_item_index (td, mono_thread_interruption_request_flag ()));
3860                                 PUSH_TYPE (td, STACK_TYPE_MP, NULL);
3861                                 ++td->ip;
3862                                 break;
3863                         case CEE_MONO_MEMORY_BARRIER:
3864                                 ADD_CODE (td, MINT_MONO_MEMORY_BARRIER);
3865                                 ++td->ip;
3866                                 break;
3867                         case CEE_MONO_JIT_ATTACH:
3868                                 ADD_CODE (td, MINT_MONO_JIT_ATTACH);
3869                                 ++td->ip;
3870                                 break;
3871                         case CEE_MONO_JIT_DETACH:
3872                                 ADD_CODE (td, MINT_MONO_JIT_DETACH);
3873                                 ++td->ip;
3874                                 break;
3875                         case CEE_MONO_LDDOMAIN:
3876                                 ADD_CODE (td, MINT_MONO_LDDOMAIN);
3877                                 td->sp [0].type = STACK_TYPE_I;
3878                                 ++td->sp;
3879                                 ++td->ip;
3880                                 break;
3881                         default:
3882                                 g_error ("transform.c: Unimplemented opcode: 0xF0 %02x at 0x%x\n", *td->ip, td->ip-header->code);
3883                         }
3884                         break;
3885 #if 0
3886                 case CEE_PREFIX7:
3887                 case CEE_PREFIX6:
3888                 case CEE_PREFIX5:
3889                 case CEE_PREFIX4:
3890                 case CEE_PREFIX3:
3891                 case CEE_PREFIX2:
3892                 case CEE_PREFIXREF: ves_abort(); break;
3893 #endif
3894                 /*
3895                  * Note: Exceptions thrown when executing a prefixed opcode need
3896                  * to take into account the number of prefix bytes (usually the
3897                  * throw point is just (ip - n_prefix_bytes).
3898                  */
3899                 case CEE_PREFIX1: 
3900                         ++td->ip;
3901                         switch (*td->ip) {
3902 #if 0
3903                         case CEE_ARGLIST: ves_abort(); break;
3904 #endif
3905                         case CEE_CEQ:
3906                                 CHECK_STACK(td, 2);
3907                                 if (td->sp [-1].type == STACK_TYPE_O || td->sp [-1].type == STACK_TYPE_MP)
3908                                         ADD_CODE(td, MINT_CEQ_I4 + STACK_TYPE_I - STACK_TYPE_I4);
3909                                 else
3910                                         ADD_CODE(td, MINT_CEQ_I4 + td->sp [-1].type - STACK_TYPE_I4);
3911                                 --td->sp;
3912                                 SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
3913                                 ++td->ip;
3914                                 break;
3915                         case CEE_CGT:
3916                                 CHECK_STACK(td, 2);
3917                                 if (td->sp [-1].type == STACK_TYPE_O || td->sp [-1].type == STACK_TYPE_MP)
3918                                         ADD_CODE(td, MINT_CGT_I4 + STACK_TYPE_I - STACK_TYPE_I4);
3919                                 else
3920                                         ADD_CODE(td, MINT_CGT_I4 + td->sp [-1].type - STACK_TYPE_I4);
3921                                 --td->sp;
3922                                 SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
3923                                 ++td->ip;
3924                                 break;
3925                         case CEE_CGT_UN:
3926                                 CHECK_STACK(td, 2);
3927                                 if (td->sp [-1].type == STACK_TYPE_O || td->sp [-1].type == STACK_TYPE_MP)
3928                                         ADD_CODE(td, MINT_CGT_UN_I4 + STACK_TYPE_I - STACK_TYPE_I4);
3929                                 else
3930                                         ADD_CODE(td, MINT_CGT_UN_I4 + td->sp [-1].type - STACK_TYPE_I4);
3931                                 --td->sp;
3932                                 SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
3933                                 ++td->ip;
3934                                 break;
3935                         case CEE_CLT:
3936                                 CHECK_STACK(td, 2);
3937                                 if (td->sp [-1].type == STACK_TYPE_O || td->sp [-1].type == STACK_TYPE_MP)
3938                                         ADD_CODE(td, MINT_CLT_I4 + STACK_TYPE_I - STACK_TYPE_I4);
3939                                 else
3940                                         ADD_CODE(td, MINT_CLT_I4 + td->sp [-1].type - STACK_TYPE_I4);
3941                                 --td->sp;
3942                                 SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
3943                                 ++td->ip;
3944                                 break;
3945                         case CEE_CLT_UN:
3946                                 CHECK_STACK(td, 2);
3947                                 if (td->sp [-1].type == STACK_TYPE_O || td->sp [-1].type == STACK_TYPE_MP)
3948                                         ADD_CODE(td, MINT_CLT_UN_I4 + STACK_TYPE_I - STACK_TYPE_I4);
3949                                 else
3950                                         ADD_CODE(td, MINT_CLT_UN_I4 + td->sp [-1].type - STACK_TYPE_I4);
3951                                 --td->sp;
3952                                 SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_I4);
3953                                 ++td->ip;
3954                                 break;
3955                         case CEE_LDVIRTFTN: /* fallthrough */
3956                         case CEE_LDFTN: {
3957                                 MonoMethod *m;
3958                                 if (*td->ip == CEE_LDVIRTFTN) {
3959                                         CHECK_STACK (td, 1);
3960                                         --td->sp;
3961                                 }
3962                                 token = read32 (td->ip + 1);
3963                                 if (method->wrapper_type != MONO_WRAPPER_NONE)
3964                                         m = (MonoMethod *)mono_method_get_wrapper_data (method, token);
3965                                 else 
3966                                         m = mono_get_method_full (image, token, NULL, generic_context);
3967
3968                                 if (method->wrapper_type == MONO_WRAPPER_NONE && m->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
3969                                         m = mono_marshal_get_synchronized_wrapper (m);
3970
3971                                 ADD_CODE(td, *td->ip == CEE_LDFTN ? MINT_LDFTN : MINT_LDVIRTFTN);
3972                                 ADD_CODE(td, get_data_item_index (td, mono_interp_get_imethod (domain, m, &error)));
3973                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3974                                 td->ip += 5;
3975                                 PUSH_SIMPLE_TYPE (td, STACK_TYPE_F);
3976                                 break;
3977                         }
3978                         case CEE_LDARG:
3979                                 load_arg (td, read16 (td->ip + 1));
3980                                 td->ip += 3;
3981                                 break;
3982                         case CEE_LDARGA: {
3983                                 int n = read16 (td->ip + 1);
3984                                 ADD_CODE (td, MINT_LDARGA);
3985                                 ADD_CODE (td, td->rtm->arg_offsets [n]); /* FIX for large offsets */
3986                                 PUSH_SIMPLE_TYPE(td, STACK_TYPE_MP);
3987                                 td->ip += 3;
3988                                 break;
3989                         }
3990                         case CEE_STARG:
3991                                 store_arg (td, read16 (td->ip + 1));
3992                                 td->ip += 3;
3993                                 break;
3994                         case CEE_LDLOC:
3995                                 load_local (td, read16 (td->ip + 1));
3996                                 td->ip += 3;
3997                                 break;
3998                         case CEE_LDLOCA:
3999                                 ADD_CODE(td, MINT_LDLOCA_S);
4000                                 ADD_CODE(td, td->rtm->local_offsets [read16 (td->ip + 1)]);
4001                                 PUSH_SIMPLE_TYPE(td, STACK_TYPE_MP);
4002                                 td->ip += 3;
4003                                 break;
4004                         case CEE_STLOC:
4005                                 store_local (td, read16 (td->ip + 1));
4006                                 td->ip += 3;
4007                                 break;
4008                         case CEE_LOCALLOC:
4009                                 CHECK_STACK (td, 1);
4010 #if SIZEOF_VOID_P == 8
4011                                 if (td->sp [-1].type == STACK_TYPE_I8)
4012                                         ADD_CODE(td, MINT_CONV_I4_I8);
4013 #endif                          
4014                                 ADD_CODE(td, MINT_LOCALLOC);
4015                                 if (td->sp != td->stack + 1)
4016                                         g_warning("CEE_LOCALLOC: stack not empty");
4017                                 ++td->ip;
4018                                 SET_SIMPLE_TYPE(td->sp - 1, STACK_TYPE_MP);
4019                                 break;
4020 #if 0
4021                         case CEE_UNUSED57: ves_abort(); break;
4022 #endif
4023                         case CEE_ENDFILTER:
4024                                 ADD_CODE (td, MINT_ENDFILTER);
4025                                 ++td->ip;
4026                                 break;
4027                         case CEE_UNALIGNED_:
4028                                 td->ip += 2;
4029                                 break;
4030                         case CEE_VOLATILE_:
4031                                 ++td->ip;
4032                                 volatile_ = TRUE;
4033                                 break;
4034                         case CEE_TAIL_:
4035                                 ++td->ip;
4036                                 /* FIX: should do something? */;
4037                                 // TODO: This should raise a method_tail_call profiler event.
4038                                 break;
4039                         case CEE_INITOBJ:
4040                                 CHECK_STACK(td, 1);
4041                                 token = read32 (td->ip + 1);
4042                                 klass = mini_get_class (method, token, generic_context);
4043                                 if (klass->valuetype) {
4044                                         ADD_CODE (td, MINT_INITOBJ);
4045                                         i32 = mono_class_value_size (klass, NULL);
4046                                         WRITE32 (td, &i32);
4047                                 } else {
4048                                         ADD_CODE (td, MINT_LDNULL);
4049                                         ADD_CODE (td, MINT_STIND_REF);
4050                                 }
4051                                 td->ip += 5;
4052                                 --td->sp;
4053                                 break;
4054                         case CEE_CPBLK:
4055                                 CHECK_STACK(td, 3);
4056                                 /* FIX? convert length to I8? */
4057                                 if (volatile_)
4058                                         ADD_CODE (td, MINT_MONO_MEMORY_BARRIER);
4059                                 ADD_CODE(td, MINT_CPBLK);
4060                                 BARRIER_IF_VOLATILE (td);
4061                                 td->sp -= 3;
4062                                 ++td->ip;
4063                                 break;
4064                         case CEE_READONLY_:
4065                                 readonly = TRUE;
4066                                 td->ip += 1;
4067                                 break;
4068                         case CEE_CONSTRAINED_:
4069                                 token = read32 (td->ip + 1);
4070                                 constrained_class = mini_get_class (method, token, generic_context);
4071                                 mono_class_init (constrained_class);
4072                                 td->ip += 5;
4073                                 break;
4074                         case CEE_INITBLK:
4075                                 CHECK_STACK(td, 3);
4076                                 BARRIER_IF_VOLATILE (td);
4077                                 ADD_CODE(td, MINT_INITBLK);
4078                                 td->sp -= 3;
4079                                 td->ip += 1;
4080                                 break;
4081                         case CEE_NO_:
4082                                 /* FIXME: implement */
4083                                 td->ip += 2;
4084                                 break;
4085                         case CEE_RETHROW: {
4086                                 int clause_index = td->clause_indexes [in_offset];
4087                                 g_assert (clause_index != -1);
4088                                 SIMPLE_OP (td, MINT_RETHROW);
4089                                 ADD_CODE (td, rtm->exvar_offsets [clause_index]);
4090                                 generating_code = 0;
4091                                 break;
4092                         }
4093                         case CEE_SIZEOF: {
4094                                 gint32 size;
4095                                 token = read32 (td->ip + 1);
4096                                 td->ip += 5;
4097                                 if (mono_metadata_token_table (token) == MONO_TABLE_TYPESPEC && !image_is_dynamic (method->klass->image) && !generic_context) {
4098                                         int align;
4099                                         MonoType *type = mono_type_create_from_typespec (image, token);
4100                                         size = mono_type_size (type, &align);
4101                                 } else {
4102                                         int align;
4103                                         MonoClass *szclass = mini_get_class (method, token, generic_context);
4104                                         mono_class_init (szclass);
4105 #if 0
4106                                         if (!szclass->valuetype)
4107                                                 THROW_EX (mono_exception_from_name (mono_defaults.corlib, "System", "InvalidProgramException"), ip - 5);
4108 #endif
4109                                         size = mono_type_size (&szclass->byval_arg, &align);
4110                                 } 
4111                                 ADD_CODE(td, MINT_LDC_I4);
4112                                 WRITE32(td, &size);
4113                                 PUSH_SIMPLE_TYPE(td, STACK_TYPE_I4);
4114                                 break;
4115                         }
4116                         case CEE_REFANYTYPE:
4117                                 ADD_CODE (td, MINT_REFANYTYPE);
4118                                 td->ip += 1;
4119                                 POP_VT (td, sizeof (MonoTypedRef));
4120                                 PUSH_VT (td, sizeof (gpointer));
4121                                 SET_TYPE(td->sp - 1, STACK_TYPE_VT, NULL);
4122                                 break;
4123                         default:
4124                                 g_error ("transform.c: Unimplemented opcode: 0xFE %02x (%s) at 0x%x\n", *td->ip, mono_opcode_name (256 + *td->ip), td->ip-header->code);
4125                         }
4126                         break;
4127                 default:
4128                         g_error ("transform.c: Unimplemented opcode: %02x at 0x%x\n", *td->ip, td->ip-header->code);
4129                 }
4130
4131                 if (td->new_ip - td->new_code != new_in_start_offset) 
4132                         td->last_new_ip = td->new_code + new_in_start_offset;
4133                 else if (td->is_bb_start [td->in_start - td->il_code])
4134                         td->is_bb_start [td->ip - td->il_code] = 1;
4135                         
4136                 td->last_ip = td->in_start;
4137         }
4138
4139         /* Handle relocations */
4140         for (int i = 0; i < td->relocs->len; ++i) {
4141                 Reloc *reloc = g_ptr_array_index (td->relocs, i);
4142
4143                 int offset = td->in_offsets [reloc->target] - reloc->offset;
4144
4145                 switch (reloc->type) {
4146                 case RELOC_SHORT_BRANCH:
4147                         g_assert (td->new_code [reloc->offset + 1] == 0xffff);
4148                         td->new_code [reloc->offset + 1] = offset;
4149                         break;
4150                 case RELOC_LONG_BRANCH: {
4151                         guint16 *v = (guint16 *) &offset;
4152                         g_assert (td->new_code [reloc->offset + 1] == 0xbeef);
4153                         g_assert (td->new_code [reloc->offset + 2] == 0xdead);
4154                         td->new_code [reloc->offset + 1] = *(guint16 *) v;
4155                         td->new_code [reloc->offset + 2] = *(guint16 *) (v + 1);
4156                         break;
4157                 }
4158                 case RELOC_SWITCH: {
4159                         guint16 *v = (guint16*)&offset;
4160                         td->new_code [reloc->offset] = *(guint16*)v;
4161                         td->new_code [reloc->offset + 1] = *(guint16*)(v + 1);
4162                         break;
4163                 }
4164                 default:
4165                         g_assert_not_reached ();
4166                         break;
4167                 }
4168         }
4169
4170         if (td->verbose_level) {
4171                 const guint16 *p = td->new_code;
4172                 printf("Runtime method: %s %p, VT stack size: %d\n", mono_method_full_name (method, TRUE), rtm, td->max_vt_sp);
4173                 printf("Calculated stack size: %d, stated size: %d\n", td->max_stack_height, header->max_stack);
4174                 while (p < td->new_ip) {
4175                         p = mono_interp_dis_mintop(td->new_code, p);
4176                         printf("\n");
4177                 }
4178         }
4179         g_assert (td->max_stack_height <= (header->max_stack + 1));
4180
4181         int code_len = td->new_ip - td->new_code;
4182
4183         rtm->clauses = mono_domain_alloc0 (domain, header->num_clauses * sizeof (MonoExceptionClause));
4184         memcpy (rtm->clauses, header->clauses, header->num_clauses * sizeof(MonoExceptionClause));
4185         rtm->code = mono_domain_alloc0 (domain, (td->new_ip - td->new_code) * sizeof (gushort));
4186         memcpy (rtm->code, td->new_code, (td->new_ip - td->new_code) * sizeof(gushort));
4187         g_free (td->new_code);
4188         rtm->new_body_start = rtm->code + body_start_offset;
4189         rtm->num_clauses = header->num_clauses;
4190         for (i = 0; i < header->num_clauses; i++) {
4191                 MonoExceptionClause *c = rtm->clauses + i;
4192                 int end_off = c->try_offset + c->try_len;
4193                 c->try_offset = td->in_offsets [c->try_offset];
4194                 c->try_len = td->in_offsets [end_off] - c->try_offset;
4195                 end_off = c->handler_offset + c->handler_len;
4196                 c->handler_offset = td->in_offsets [c->handler_offset];
4197                 c->handler_len = td->in_offsets [end_off] - c->handler_offset;
4198                 if (c->flags & MONO_EXCEPTION_CLAUSE_FILTER)
4199                         c->data.filter_offset = td->in_offsets [c->data.filter_offset];
4200         }
4201         rtm->vt_stack_size = td->max_vt_sp;
4202         rtm->alloca_size = rtm->locals_size + rtm->args_size + rtm->vt_stack_size + rtm->stack_size;
4203         rtm->data_items = mono_domain_alloc0 (domain, td->n_data_items * sizeof (td->data_items [0]));
4204         memcpy (rtm->data_items, td->data_items, td->n_data_items * sizeof (td->data_items [0]));
4205
4206         /* Save debug info */
4207         interp_save_debug_info (rtm, header, td, line_numbers);
4208
4209         /* Create a MonoJitInfo for the interpreted method by creating the interpreter IR as the native code. */
4210         int jinfo_len = mono_jit_info_size (0, header->num_clauses, 0);
4211         MonoJitInfo *jinfo = (MonoJitInfo *)mono_domain_alloc0 (domain, jinfo_len);
4212         jinfo->is_interp = 1;
4213         rtm->jinfo = jinfo;
4214         mono_jit_info_init (jinfo, method, (guint8*)rtm->code, code_len, 0, header->num_clauses, 0);
4215         for (i = 0; i < jinfo->num_clauses; ++i) {
4216                 MonoJitExceptionInfo *ei = &jinfo->clauses [i];
4217                 MonoExceptionClause *c = rtm->clauses + i;
4218
4219                 ei->flags = c->flags;
4220                 ei->try_start = (guint8*)(rtm->code + c->try_offset);
4221                 ei->try_end = (guint8*)(rtm->code + c->try_offset + c->try_len);
4222                 ei->handler_start = (guint8*)(rtm->code + c->handler_offset);
4223                 ei->exvar_offset = rtm->exvar_offsets [i];
4224                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
4225                         ei->data.filter = (guint8*)(rtm->code + c->data.filter_offset);
4226                 } else if (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
4227                 } else {
4228                         ei->data.catch_class = c->data.catch_class;
4229                 }
4230         }
4231
4232         save_seq_points (td);
4233
4234         g_free (td->in_offsets);
4235         for (i = 0; i < header->code_size; ++i)
4236                 g_free (td->stack_state [i]);
4237         g_free (td->stack_state);
4238         g_free (td->stack_height);
4239         g_free (td->vt_stack_size);
4240         g_free (td->data_items);
4241         g_free (td->stack);
4242         g_hash_table_destroy (td->data_hash);
4243         g_free (td->clause_indexes);
4244         g_ptr_array_free (td->seq_points, TRUE);
4245         g_array_free (line_numbers, TRUE);
4246         g_ptr_array_free (td->relocs, TRUE);
4247         mono_mempool_destroy (td->mempool);
4248 }
4249
4250 static mono_mutex_t calc_section;
4251
4252 void 
4253 mono_interp_transform_init (void)
4254 {
4255         mono_os_mutex_init_recursive(&calc_section);
4256 }
4257
4258 MonoException *
4259 mono_interp_transform_method (InterpMethod *imethod, ThreadContext *context)
4260 {
4261         MonoError error;
4262         int i, align, size, offset;
4263         MonoMethod *method = imethod->method;
4264         MonoImage *image = method->klass->image;
4265         MonoMethodHeader *header = mono_method_get_header (method);
4266         MonoMethodSignature *signature = mono_method_signature (method);
4267         register const unsigned char *ip, *end;
4268         const MonoOpcode *opcode;
4269         MonoMethod *m;
4270         MonoClass *class;
4271         unsigned char *is_bb_start;
4272         int in;
4273         MonoVTable *method_class_vt;
4274         int backwards;
4275         MonoGenericContext *generic_context = NULL;
4276         MonoDomain *domain = imethod->domain;
4277
4278         // g_printerr ("TRANSFORM(0x%016lx): begin %s::%s\n", mono_thread_current (), method->klass->name, method->name);
4279         method_class_vt = mono_class_vtable_full (domain, imethod->method->klass, &error);
4280         if (!is_ok (&error))
4281                 return mono_error_convert_to_exception (&error);
4282
4283         if (!method_class_vt->initialized) {
4284                 jmp_buf env;
4285                 InterpFrame *last_env_frame = context->env_frame;
4286                 jmp_buf *old_env = context->current_env;
4287                 error_init (&error);
4288
4289                 if (setjmp(env)) {
4290                         MonoException *failed = context->env_frame->ex;
4291                         context->env_frame->ex = NULL;
4292                         context->env_frame = last_env_frame;
4293                         context->current_env = old_env;
4294                         return failed;
4295                 }
4296                 context->env_frame = context->current_frame;
4297                 context->current_env = &env;
4298                 mono_runtime_class_init_full (method_class_vt, &error);
4299                 if (!mono_error_ok (&error)) {
4300                         return mono_error_convert_to_exception (&error);
4301                 }
4302                 context->env_frame = last_env_frame;
4303                 context->current_env = old_env;
4304         }
4305
4306         MONO_PROFILER_RAISE (jit_begin, (method));
4307
4308         if (mono_method_signature (method)->is_inflated)
4309                 generic_context = mono_method_get_context (method);
4310         else {
4311                 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
4312                 if (generic_container)
4313                         generic_context = &generic_container->context;
4314         }
4315
4316         if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
4317                 MonoMethod *nm = NULL;
4318                 mono_os_mutex_lock(&calc_section);
4319                 if (imethod->transformed) {
4320                         mono_os_mutex_unlock(&calc_section);
4321                         MONO_PROFILER_RAISE (jit_done, (method, imethod->jinfo));
4322                         return NULL;
4323                 }
4324
4325                 /* assumes all internal calls with an array this are built in... */
4326                 if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL && (! mono_method_signature (method)->hasthis || method->klass->rank == 0)) {
4327                         nm = mono_marshal_get_native_wrapper (method, TRUE, FALSE);
4328                         signature = mono_method_signature (nm);
4329                 } else {
4330                         const char *name = method->name;
4331                         if (method->klass->parent == mono_defaults.multicastdelegate_class) {
4332                                 if (*name == '.' && (strcmp (name, ".ctor") == 0)) {
4333                                         MonoJitICallInfo *mi = mono_find_jit_icall_by_name ("ves_icall_mono_delegate_ctor");
4334                                         g_assert (mi);
4335                                         char *wrapper_name = g_strdup_printf ("__icall_wrapper_%s", mi->name);
4336                                         nm = mono_marshal_get_icall_wrapper (mi->sig, wrapper_name, mi->func, TRUE);
4337                                 } else if (*name == 'I' && (strcmp (name, "Invoke") == 0)) {
4338                                         nm = mono_marshal_get_delegate_invoke (method, NULL);
4339                                 } else if (*name == 'B' && (strcmp (name, "BeginInvoke") == 0)) {
4340                                         nm = mono_marshal_get_delegate_begin_invoke (method);
4341                                 } else if (*name == 'E' && (strcmp (name, "EndInvoke") == 0)) {
4342                                         nm = mono_marshal_get_delegate_end_invoke (method);
4343                                 }
4344                         }
4345                         if (nm == NULL) {
4346                                 imethod->code = g_malloc(sizeof(short));
4347                                 imethod->code[0] = MINT_CALLRUN;
4348                         }
4349                 }
4350                 if (nm == NULL) {
4351                         imethod->stack_size = sizeof (stackval); /* for tracing */
4352                         imethod->alloca_size = imethod->stack_size;
4353                         imethod->transformed = TRUE;
4354                         mono_os_mutex_unlock(&calc_section);
4355                         MONO_PROFILER_RAISE (jit_done, (method, NULL));
4356                         return NULL;
4357                 }
4358                 method = nm;
4359                 header = mono_method_get_header (nm);
4360                 mono_os_mutex_unlock(&calc_section);
4361         } else if (method->klass == mono_defaults.array_class) {
4362                 if (!strcmp (method->name, "UnsafeMov") || !strcmp (method->name, "UnsafeLoad")) {
4363                         mono_os_mutex_lock (&calc_section);
4364                         if (!imethod->transformed) {
4365                                 imethod->code = g_malloc (sizeof (short));
4366                                 imethod->code[0] = MINT_CALLRUN;
4367                                 imethod->stack_size = sizeof (stackval); /* for tracing */
4368                                 imethod->alloca_size = imethod->stack_size;
4369                                 imethod->transformed = TRUE;
4370                         }
4371                         mono_os_mutex_unlock(&calc_section);
4372                         MONO_PROFILER_RAISE (jit_done, (method, NULL));
4373                         return NULL;
4374                 } else if (!strcmp (method->name, "UnsafeStore")) {
4375                         g_error ("TODO");
4376                 }
4377         }
4378         g_assert ((signature->param_count + signature->hasthis) < 1000);
4379         g_assert (header->max_stack < 10000);
4380         /* intern the strings in the method. */
4381         ip = header->code;
4382         end = ip + header->code_size;
4383
4384         is_bb_start = g_malloc0(header->code_size);
4385         is_bb_start [0] = 1;
4386         while (ip < end) {
4387                 in = *ip;
4388                 if (in == 0xfe) {
4389                         ip++;
4390                         in = *ip + 256;
4391                 }
4392                 else if (in == 0xf0) {
4393                         ip++;
4394                         in = *ip + MONO_CEE_MONO_ICALL;
4395                 }
4396                 opcode = &mono_opcodes [in];
4397                 switch (opcode->argument) {
4398                 case MonoInlineNone:
4399                         ++ip;
4400                         break;
4401                 case MonoInlineString:
4402                         if (method->wrapper_type == MONO_WRAPPER_NONE)
4403                                 mono_ldstr (domain, image, mono_metadata_token_index (read32 (ip + 1)));
4404                         ip += 5;
4405                         break;
4406                 case MonoInlineType:
4407                         if (method->wrapper_type == MONO_WRAPPER_NONE) {
4408                                 class = mini_get_class (method, read32 (ip + 1), generic_context);
4409                                 mono_class_init (class);
4410                                 /* quick fix to not do this for the fake ptr classes - probably should not be getting the vtable at all here */
4411 #if 0
4412                                 g_error ("FIXME: interface method lookup: %s (in method %s)", class->name, method->name);
4413                                 if (!(class->flags & TYPE_ATTRIBUTE_INTERFACE) && class->interface_offsets != NULL)
4414                                         mono_class_vtable (domain, class);
4415 #endif
4416                         }
4417                         ip += 5;
4418                         break;
4419                 case MonoInlineMethod:
4420                         if (method->wrapper_type == MONO_WRAPPER_NONE && *ip != CEE_CALLI) {
4421                                 m = mono_get_method_checked (image, read32 (ip + 1), NULL, generic_context, &error);
4422                                 if (!is_ok (&error)) {
4423                                         g_free (is_bb_start);
4424                                         return mono_error_convert_to_exception (&error);
4425                                 }
4426                                 mono_class_init (m->klass);
4427                                 if (!mono_class_is_interface (m->klass))
4428                                         mono_class_vtable (domain, m->klass);
4429                         }
4430                         ip += 5;
4431                         break;
4432                 case MonoInlineField:
4433                 case MonoInlineSig:
4434                 case MonoInlineI:
4435                 case MonoInlineTok:
4436                 case MonoShortInlineR:
4437                         ip += 5;
4438                         break;
4439                 case MonoInlineBrTarget:
4440                         offset = read32 (ip + 1);
4441                         ip += 5;
4442                         backwards = offset < 0;
4443                         offset += ip - header->code;
4444                         g_assert (offset >= 0 && offset < header->code_size);
4445                         is_bb_start [offset] |= backwards ? 2 : 1;
4446                         break;
4447                 case MonoShortInlineBrTarget:
4448                         offset = ((gint8 *)ip) [1];
4449                         ip += 2;
4450                         backwards = offset < 0;
4451                         offset += ip - header->code;
4452                         g_assert (offset >= 0 && offset < header->code_size);
4453                         is_bb_start [offset] |= backwards ? 2 : 1;
4454                         break;
4455                 case MonoInlineVar:
4456                         ip += 3;
4457                         break;
4458                 case MonoShortInlineVar:
4459                 case MonoShortInlineI:
4460                         ip += 2;
4461                         break;
4462                 case MonoInlineSwitch: {
4463                         guint32 n;
4464                         const unsigned char *next_ip;
4465                         ++ip;
4466                         n = read32 (ip);
4467                         ip += 4;
4468                         next_ip = ip + 4 * n;
4469                         for (i = 0; i < n; i++) {
4470                                 offset = read32 (ip);
4471                                 backwards = offset < 0;
4472                                 offset += next_ip - header->code;
4473                                 g_assert (offset >= 0 && offset < header->code_size);
4474                                 is_bb_start [offset] |= backwards ? 2 : 1;
4475                                 ip += 4;
4476                         }
4477                         break;
4478                 }
4479                 case MonoInlineR:
4480                 case MonoInlineI8:
4481                         ip += 9;
4482                         break;
4483                 default:
4484                         g_assert_not_reached ();
4485                 }
4486         }
4487         // g_printerr ("TRANSFORM(0x%016lx): end %s::%s\n", mono_thread_current (), method->klass->name, method->name);
4488
4489         /* the rest needs to be locked so it is only done once */
4490         mono_os_mutex_lock(&calc_section);
4491         if (imethod->transformed) {
4492                 mono_os_mutex_unlock(&calc_section);
4493                 g_free (is_bb_start);
4494                 MONO_PROFILER_RAISE (jit_done, (method, imethod->jinfo));
4495                 return NULL;
4496         }
4497
4498         imethod->local_offsets = g_malloc (header->num_locals * sizeof(guint32));
4499         imethod->stack_size = (sizeof (stackval)) * (header->max_stack + 2); /* + 1 for returns of called functions  + 1 for 0-ing in trace*/
4500         imethod->stack_size = (imethod->stack_size + 7) & ~7;
4501         offset = 0;
4502         for (i = 0; i < header->num_locals; ++i) {
4503                 size = mono_type_size (header->locals [i], &align);
4504                 offset += align - 1;
4505                 offset &= ~(align - 1);
4506                 imethod->local_offsets [i] = offset;
4507                 offset += size;
4508         }
4509         offset = (offset + 7) & ~7;
4510
4511         imethod->exvar_offsets = g_malloc (header->num_clauses * sizeof (guint32));
4512         for (i = 0; i < header->num_clauses; i++) {
4513                 offset += sizeof (MonoObject*);
4514                 imethod->exvar_offsets [i] = offset;
4515         }
4516         offset = (offset + 7) & ~7;
4517
4518         imethod->locals_size = offset;
4519         g_assert (imethod->locals_size < 65536);
4520         offset = 0;
4521         imethod->arg_offsets = g_malloc ((!!signature->hasthis + signature->param_count) * sizeof(guint32));
4522
4523         if (signature->hasthis) {
4524                 g_assert (!signature->pinvoke);
4525                 size = mono_type_stack_size (&method->klass->byval_arg, &align);
4526                 offset += align - 1;
4527                 offset &= ~(align - 1);
4528                 imethod->arg_offsets [0] = offset;
4529                 offset += size;
4530         }
4531
4532         for (i = 0; i < signature->param_count; ++i) {
4533                 if (signature->pinvoke) {
4534                         guint32 dummy;
4535                         size = mono_type_native_stack_size (signature->params [i], &dummy);
4536                         align = 8;
4537                 }
4538                 else
4539                         size = mono_type_stack_size (signature->params [i], &align);
4540                 offset += align - 1;
4541                 offset &= ~(align - 1);
4542                 imethod->arg_offsets [i + !!signature->hasthis] = offset;
4543                 offset += size;
4544         }
4545         offset = (offset + 7) & ~7;
4546         imethod->args_size = offset;
4547         g_assert (imethod->args_size < 10000);
4548
4549         generate (method, imethod, is_bb_start, generic_context);
4550
4551         g_free (is_bb_start);
4552
4553         // FIXME: Add a different callback ?
4554         MONO_PROFILER_RAISE (jit_done, (method, imethod->jinfo));
4555         imethod->transformed = TRUE;
4556         mono_os_mutex_unlock(&calc_section);
4557
4558         return NULL;
4559 }
4560