Merge pull request #4799 from xmcclure/mingw-has-secure-api
[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
19 #include <mono/mini/mini.h>
20
21 #include "mintops.h"
22 #include "interp-internals.h"
23 #include "interp.h"
24
25 // TODO: export from marshal.c
26 MonoDelegate* mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn);
27
28 #define DEBUG 0
29
30 typedef struct
31 {
32         MonoClass *klass;
33         unsigned char type;
34         unsigned char flags;
35 } StackInfo;
36
37 typedef struct
38 {
39         MonoMethod *method;
40         MonoMethodHeader *header;
41         RuntimeMethod *rtm;
42         const unsigned char *il_code;
43         const unsigned char *ip;
44         const unsigned char *last_ip;
45         const unsigned char *in_start;
46         int code_size;
47         int *in_offsets;
48         int *forward_refs;
49         StackInfo **stack_state;
50         int *stack_height;
51         int *vt_stack_size;
52         unsigned char *is_bb_start;
53         unsigned short *new_code;
54         unsigned short *new_code_end;
55         unsigned short *new_ip;
56         unsigned short *last_new_ip;
57         unsigned int max_code_size;
58         StackInfo *stack;
59         StackInfo *sp;
60         unsigned int max_stack_height;
61         unsigned int vt_sp;
62         unsigned int max_vt_sp;
63         int n_data_items;
64         int max_data_items;
65         void **data_items;
66         GHashTable *data_hash;
67         int *clause_indexes;
68 } TransformData;
69
70 #define MINT_TYPE_I1 0
71 #define MINT_TYPE_U1 1
72 #define MINT_TYPE_I2 2
73 #define MINT_TYPE_U2 3
74 #define MINT_TYPE_I4 4
75 #define MINT_TYPE_I8 5
76 #define MINT_TYPE_R4 6
77 #define MINT_TYPE_R8 7
78 #define MINT_TYPE_O  8
79 #define MINT_TYPE_P  9
80 #define MINT_TYPE_VT 10
81
82 #define STACK_TYPE_I4 0
83 #define STACK_TYPE_I8 1
84 #define STACK_TYPE_R8 2
85 #define STACK_TYPE_O  3
86 #define STACK_TYPE_VT 4
87 #define STACK_TYPE_MP 5
88 #define STACK_TYPE_F  6
89
90 static const char *stack_type_string [] = { "I4", "I8", "R8", "O ", "VT", "MP", "F " };
91
92 #if SIZEOF_VOID_P == 8
93 #define STACK_TYPE_I STACK_TYPE_I8
94 #else
95 #define STACK_TYPE_I STACK_TYPE_I4
96 #endif
97
98 static int stack_type [] = {
99         STACK_TYPE_I4, /*I1*/
100         STACK_TYPE_I4, /*U1*/
101         STACK_TYPE_I4, /*I2*/
102         STACK_TYPE_I4, /*U2*/
103         STACK_TYPE_I4, /*I4*/
104         STACK_TYPE_I8, /*I8*/
105         STACK_TYPE_R8, /*R4*/
106         STACK_TYPE_R8, /*R8*/
107         STACK_TYPE_O,  /*O*/
108         STACK_TYPE_MP, /*P*/
109         STACK_TYPE_VT
110 };
111
112 static void
113 grow_code (TransformData *td)
114 {
115         unsigned int old_ip_offset = td->new_ip - td->new_code;
116         unsigned int old_last_ip_offset = td->last_new_ip - td->new_code;
117         g_assert (old_ip_offset <= td->max_code_size);
118         td->new_code = g_realloc (td->new_code, (td->max_code_size *= 2) * sizeof (td->new_code [0]));
119         td->new_code_end = td->new_code + td->max_code_size;
120         td->new_ip = td->new_code + old_ip_offset;
121         td->last_new_ip = td->new_code + old_last_ip_offset;
122 }
123
124 #define ENSURE_CODE(td, n) \
125         do { \
126                 if ((td)->new_ip + (n) > (td)->new_code_end) \
127                         grow_code (td); \
128         } while (0)
129
130 #define ADD_CODE(td, n) \
131         do { \
132                 if ((td)->new_ip == (td)->new_code_end) \
133                         grow_code (td); \
134                 *(td)->new_ip++ = (n); \
135         } while (0)
136
137 #define CHECK_STACK(td, n) \
138         do { \
139                 int stack_size = (td)->sp - (td)->stack; \
140                 if (stack_size < (n)) \
141                         g_warning ("%s.%s: not enough values (%d < %d) on stack at %04x", \
142                                 (td)->method->klass->name, (td)->method->name, \
143                                 stack_size, n, (td)->ip - (td)->il_code); \
144         } while (0)
145
146 #define ENSURE_I4(td, sp_off) \
147         do { \
148                 if ((td)->sp [-sp_off].type == STACK_TYPE_I8) \
149                         ADD_CODE(td, sp_off == 1 ? MINT_CONV_I4_I8 : MINT_CONV_I4_I8_SP); \
150         } while (0)
151
152 static void 
153 handle_branch(TransformData *td, int short_op, int long_op, int offset) 
154 {
155         int shorten_branch = 0;
156         int target = td->ip + offset - td->il_code;
157         if (target < 0 || target >= td->code_size)
158                 g_assert_not_reached ();
159         if (offset > 0 && td->stack_height [target] < 0) {
160                 td->stack_height [target] = td->sp - td->stack;
161                 if (td->stack_height [target] > 0)
162                         td->stack_state [target] = g_memdup (td->stack, td->stack_height [target] * sizeof (td->stack [0]));
163                 td->vt_stack_size [target] = td->vt_sp;
164         }
165         if (offset < 0) {
166                 offset = td->in_offsets [target] - (td->new_ip - td->new_code);
167                 if (offset >= -32768) {
168                         shorten_branch = 1;
169                 }
170         } else {
171                 int prev = td->forward_refs [target];
172                 td->forward_refs [td->ip - td->il_code] = prev;
173                 td->forward_refs [target] = td->ip - td->il_code;
174                 offset = 0;
175                 if (td->header->code_size <= 25000) /* FIX to be precise somehow? */
176                         shorten_branch = 1;
177         }
178         if (shorten_branch) {
179                 ADD_CODE(td, short_op);
180                 ADD_CODE(td, offset);
181         } else {
182                 ADD_CODE(td, long_op);
183                 ADD_CODE(td, * (unsigned short *)(&offset));
184                 ADD_CODE(td, * ((unsigned short *)&offset + 1));
185         }
186 }
187
188 static void 
189 one_arg_branch(TransformData *td, int mint_op, int offset) 
190 {
191         int type = td->sp [-1].type == STACK_TYPE_O || td->sp [-1].type == STACK_TYPE_MP ? STACK_TYPE_I : td->sp [-1].type;
192         int long_op = mint_op + type - STACK_TYPE_I4;
193         int short_op = long_op + MINT_BRFALSE_I4_S - MINT_BRFALSE_I4;
194         CHECK_STACK(td, 1);
195         --td->sp;
196         handle_branch (td, short_op, long_op, offset);
197 }
198
199 static void 
200 two_arg_branch(TransformData *td, int mint_op, int offset) 
201 {
202         int type1 = td->sp [-1].type == STACK_TYPE_O || td->sp [-1].type == STACK_TYPE_MP ? STACK_TYPE_I : td->sp [-1].type;
203         int type2 = td->sp [-2].type == STACK_TYPE_O || td->sp [-2].type == STACK_TYPE_MP ? STACK_TYPE_I : td->sp [-2].type;
204         int long_op = mint_op + type1 - STACK_TYPE_I4;
205         int short_op = long_op + MINT_BEQ_I4_S - MINT_BEQ_I4;
206         CHECK_STACK(td, 2);
207         if (type1 == STACK_TYPE_I4 && type2 == STACK_TYPE_I8) {
208                 ADD_CODE(td, MINT_CONV_I8_I4);
209                 td->in_offsets [td->ip - td->il_code]++;
210         } else if (type1 == STACK_TYPE_I8 && type2 == STACK_TYPE_I4) {
211                 ADD_CODE(td, MINT_CONV_I8_I4_SP);
212                 td->in_offsets [td->ip - td->il_code]++;
213         } else if (type1 != type2) {
214                 g_warning("%s.%s: branch type mismatch %d %d", 
215                         td->method->klass->name, td->method->name, 
216                         td->sp [-1].type, td->sp [-2].type);
217         }
218         td->sp -= 2;
219         handle_branch (td, short_op, long_op, offset);
220 }
221
222 static void
223 unary_arith_op(TransformData *td, int mint_op)
224 {
225         int op = mint_op + td->sp [-1].type - STACK_TYPE_I4;
226         CHECK_STACK(td, 1);
227         ADD_CODE(td, op);
228 }
229
230 static void
231 binary_arith_op(TransformData *td, int mint_op)
232 {
233         int type1 = td->sp [-2].type;
234         int type2 = td->sp [-1].type;
235         int op;
236 #if SIZEOF_VOID_P == 8
237         if ((type1 == STACK_TYPE_MP || type1 == STACK_TYPE_I8) && type2 == STACK_TYPE_I4) {
238                 ADD_CODE(td, MINT_CONV_I8_I4);
239                 type2 = STACK_TYPE_I8;
240         }
241         if (type1 == STACK_TYPE_I4 && (type2 == STACK_TYPE_MP || type2 == STACK_TYPE_I8)) {
242                 ADD_CODE(td, MINT_CONV_I8_I4_SP);
243                 type1 = STACK_TYPE_I8;
244                 td->sp [-2].type = STACK_TYPE_I8;
245         }
246 #endif
247         if (type1 == STACK_TYPE_MP)
248                 type1 = STACK_TYPE_I;
249         if (type2 == STACK_TYPE_MP)
250                 type2 = STACK_TYPE_I;
251         if (type1 != type2) {
252                 g_warning("%s.%s: %04x arith type mismatch %s %d %d", 
253                         td->method->klass->name, td->method->name, 
254                         td->ip - td->il_code, mono_interp_opname[mint_op], type1, type2);
255         }
256         op = mint_op + type1 - STACK_TYPE_I4;
257         CHECK_STACK(td, 2);
258         ADD_CODE(td, op);
259         --td->sp;
260 }
261
262 static void
263 shift_op(TransformData *td, int mint_op)
264 {
265         int op = mint_op + td->sp [-2].type - STACK_TYPE_I4;
266         CHECK_STACK(td, 2);
267         if (td->sp [-1].type != STACK_TYPE_I4) {
268                 g_warning("%s.%s: shift type mismatch %d", 
269                         td->method->klass->name, td->method->name,
270                         td->sp [-2].type);
271         }
272         ADD_CODE(td, op);
273         --td->sp;
274 }
275
276 static int 
277 mint_type(MonoType *type)
278 {
279         if (type->byref)
280                 return MINT_TYPE_P;
281 enum_type:
282         switch (type->type) {
283         case MONO_TYPE_I1:
284                 return MINT_TYPE_I1;
285         case MONO_TYPE_U1:
286         case MONO_TYPE_BOOLEAN:
287                 return MINT_TYPE_U1;
288         case MONO_TYPE_I2:
289                 return MINT_TYPE_I2;
290         case MONO_TYPE_U2:
291         case MONO_TYPE_CHAR:
292                 return MINT_TYPE_U2;
293         case MONO_TYPE_I4:
294         case MONO_TYPE_U4:
295                 return MINT_TYPE_I4;
296         case MONO_TYPE_I:
297         case MONO_TYPE_U:
298 #if SIZEOF_VOID_P == 4
299                 return MINT_TYPE_I4;
300 #else
301                 return MINT_TYPE_I8;
302 #endif
303         case MONO_TYPE_PTR:
304                 return MINT_TYPE_P;
305         case MONO_TYPE_R4:
306                 return MINT_TYPE_R4;
307         case MONO_TYPE_I8:
308         case MONO_TYPE_U8:
309                 return MINT_TYPE_I8;
310         case MONO_TYPE_R8:
311                 return MINT_TYPE_R8;
312         case MONO_TYPE_STRING:
313         case MONO_TYPE_SZARRAY:
314         case MONO_TYPE_CLASS:
315         case MONO_TYPE_OBJECT:
316         case MONO_TYPE_ARRAY:
317                 return MINT_TYPE_O;
318         case MONO_TYPE_VALUETYPE:
319                 if (type->data.klass->enumtype) {
320                         type = mono_class_enum_basetype (type->data.klass);
321                         goto enum_type;
322                 } else
323                         return MINT_TYPE_VT;
324         case MONO_TYPE_GENERICINST:
325                 type = &type->data.generic_class->container_class->byval_arg;
326                 goto enum_type;
327         default:
328                 g_warning ("got type 0x%02x", type->type);
329                 g_assert_not_reached ();
330         }
331         return -1;
332 }
333
334 static int 
335 can_store (int stack_type, int var_type)
336 {
337         if (stack_type == STACK_TYPE_O || stack_type == STACK_TYPE_MP)
338                 stack_type = STACK_TYPE_I;
339         if (var_type == STACK_TYPE_O || var_type == STACK_TYPE_MP)
340                 var_type = STACK_TYPE_I;
341         return stack_type == var_type;
342 }
343
344 #define SET_SIMPLE_TYPE(s, ty) \
345         do { \
346                 (s)->type = (ty); \
347                 (s)->flags = 0; \
348                 (s)->klass = NULL; \
349         } while (0)
350
351 #define SET_TYPE(s, ty, k) \
352         do { \
353                 (s)->type = (ty); \
354                 (s)->flags = 0; \
355                 (s)->klass = k; \
356         } while (0)
357
358 #define PUSH_SIMPLE_TYPE(td, ty) \
359         do { \
360                 int sp_height; \
361                 (td)->sp++; \
362                 sp_height = (td)->sp - (td)->stack; \
363                 if (sp_height > (td)->max_stack_height) \
364                         (td)->max_stack_height = sp_height; \
365                 SET_SIMPLE_TYPE((td)->sp - 1, ty); \
366         } while (0)
367
368 #define PUSH_TYPE(td, ty, k) \
369         do { \
370                 int sp_height; \
371                 (td)->sp++; \
372                 sp_height = (td)->sp - (td)->stack; \
373                 if (sp_height > (td)->max_stack_height) \
374                         (td)->max_stack_height = sp_height; \
375                 SET_TYPE((td)->sp - 1, ty, k); \
376         } while (0)
377
378 #define PUSH_VT(td, size) \
379         do { \
380                 (td)->vt_sp += ((size) + 7) & ~7; \
381                 if ((td)->vt_sp > (td)->max_vt_sp) \
382                         (td)->max_vt_sp = (td)->vt_sp; \
383         } while (0)
384
385 #define POP_VT(td, size) \
386         do { \
387                 (td)->vt_sp -= ((size) + 7) & ~7; \
388         } while (0)
389
390 #if NO_UNALIGNED_ACCESS
391 #define WRITE32(td, v) \
392         do { \
393                 ENSURE_CODE(td, 2); \
394                 * (guint16 *)((td)->new_ip) = * (guint16 *)(v); \
395                 * ((guint16 *)((td)->new_ip) + 1) = * ((guint16 *)(v) + 1); \
396                 (td)->new_ip += 2; \
397         } while (0)
398
399 #define WRITE64(td, v) \
400         do { \
401                 ENSURE_CODE(td, 4); \
402                 * (guint16 *)((td)->new_ip) = * (guint16 *)(v); \
403                 * ((guint16 *)((td)->new_ip) + 1) = * ((guint16 *)(v) + 1); \
404                 * ((guint16 *)((td)->new_ip) + 2) = * ((guint16 *)(v) + 2); \
405                 * ((guint16 *)((td)->new_ip) + 3) = * ((guint16 *)(v) + 3); \
406                 (td)->new_ip += 4; \
407         } while (0)
408 #else
409 #define WRITE32(td, v) \
410         do { \
411                 ENSURE_CODE(td, 2); \
412                 * (guint32 *)((td)->new_ip) = * (guint32 *)(v); \
413                 (td)->new_ip += 2; \
414         } while (0)
415
416 #define WRITE64(td, v) \
417         do { \
418                 ENSURE_CODE(td, 4); \
419                 * (guint64 *)((td)->new_ip) = * (guint64 *)(v); \
420                 (td)->new_ip += 4; \
421         } while (0)
422
423 #endif
424
425 static void 
426 load_arg(TransformData *td, int n)
427 {
428         int mt;
429         MonoClass *klass = NULL;
430         MonoType *type;
431
432         gboolean hasthis = mono_method_signature (td->method)->hasthis;
433         if (hasthis && n == 0)
434                 type = &td->method->klass->byval_arg;
435         else
436                 type = mono_method_signature (td->method)->params [hasthis ? n - 1 : n];
437
438         mt = mint_type (type);
439         if (mt == MINT_TYPE_VT) {
440                 gint32 size;
441                 klass = mono_class_from_mono_type (type);
442                 if (mono_method_signature (td->method)->pinvoke)
443                         size = mono_class_native_size (klass, NULL);
444                 else
445                         size = mono_class_value_size (klass, NULL);
446
447                 if (hasthis && n == 0) {
448                         mt = MINT_TYPE_P;
449                         ADD_CODE (td, MINT_LDARG_P);
450                         ADD_CODE (td, td->rtm->arg_offsets [n]); /* FIX for large offset */
451                         klass = NULL;
452                 } else {
453                         PUSH_VT (td, size);
454                         ADD_CODE (td, MINT_LDARG_VT);
455                         ADD_CODE (td, td->rtm->arg_offsets [n]); /* FIX for large offset */
456                         WRITE32 (td, &size);
457                 }
458         } else {
459                 if (hasthis && n == 0) {
460                         mt = MINT_TYPE_P;
461                         ADD_CODE (td, MINT_LDARG_P);
462                         ADD_CODE (td, td->rtm->arg_offsets [n]); /* FIX for large offset */
463                         klass = NULL;
464                 } else {
465                         ADD_CODE(td, MINT_LDARG_I1 + (mt - MINT_TYPE_I1));
466                         ADD_CODE(td, td->rtm->arg_offsets [n]); /* FIX for large offset */
467                         if (mt == MINT_TYPE_O)
468                                 klass = mono_class_from_mono_type (type);
469                 }
470         }
471         PUSH_TYPE(td, stack_type[mt], klass);
472 }
473
474 static void 
475 store_arg(TransformData *td, int n)
476 {
477         int mt;
478         CHECK_STACK (td, 1);
479         MonoType *type;
480
481         gboolean hasthis = mono_method_signature (td->method)->hasthis;
482         if (hasthis && n == 0)
483                 type = &td->method->klass->byval_arg;
484         else
485                 type = mono_method_signature (td->method)->params [n - !!hasthis];
486
487         mt = mint_type (type);
488         if (mt == MINT_TYPE_VT) {
489                 gint32 size;
490                 MonoClass *klass = mono_class_from_mono_type (type);
491                 if (mono_method_signature (td->method)->pinvoke)
492                         size = mono_class_native_size (klass, NULL);
493                 else
494                         size = mono_class_value_size (klass, NULL);
495                 ADD_CODE(td, MINT_STARG_VT);
496                 ADD_CODE(td, td->rtm->arg_offsets [n]);
497                 WRITE32(td, &size);
498                 if (td->sp [-1].type == STACK_TYPE_VT)
499                         POP_VT(td, size);
500         } else {
501                 ADD_CODE(td, MINT_STARG_I1 + (mt - MINT_TYPE_I1));
502                 ADD_CODE(td, td->rtm->arg_offsets [n]);
503         }
504         --td->sp;
505 }
506
507 static void 
508 store_inarg(TransformData *td, int n)
509 {
510         MonoType *type;
511         gboolean hasthis = mono_method_signature (td->method)->hasthis;
512         if (hasthis && n == 0)
513                 type = &td->method->klass->byval_arg;
514         else
515                 type = mono_method_signature (td->method)->params [n - !!hasthis];
516
517         int mt = mint_type (type);
518         if (hasthis && n == 0) {
519                 ADD_CODE (td, MINT_STINARG_P);
520                 ADD_CODE (td, n);
521                 return;
522         }
523         if (mt == MINT_TYPE_VT) {
524                 MonoClass *klass = mono_class_from_mono_type (type);
525                 gint32 size;
526                 if (mono_method_signature (td->method)->pinvoke)
527                         size = mono_class_native_size (klass, NULL);
528                 else
529                         size = mono_class_value_size (klass, NULL);
530                 ADD_CODE(td, MINT_STINARG_VT);
531                 ADD_CODE(td, n);
532                 WRITE32(td, &size);
533         } else {
534                 ADD_CODE(td, MINT_STINARG_I1 + (mt - MINT_TYPE_I1));
535                 ADD_CODE(td, n);
536         }
537 }
538
539 static void 
540 load_local(TransformData *td, int n)
541 {
542         MonoType *type = td->header->locals [n];
543         int mt = mint_type (type);
544         int offset = td->rtm->local_offsets [n];
545         MonoClass *klass = NULL;
546         if (mt == MINT_TYPE_VT) {
547                 klass = mono_class_from_mono_type (type);
548                 gint32 size = mono_class_value_size (klass, NULL);
549                 PUSH_VT(td, size);
550                 ADD_CODE(td, MINT_LDLOC_VT);
551                 ADD_CODE(td, offset); /*FIX for large offset */
552                 WRITE32(td, &size);
553         } else {
554                 g_assert (mt < MINT_TYPE_VT);
555                 if (mt == MINT_TYPE_I4 && !td->is_bb_start [td->in_start - td->il_code] && td->last_new_ip != NULL &&
556                         td->last_new_ip [0] == MINT_STLOC_I4 && td->last_new_ip [1] == offset) {
557                         td->last_new_ip [0] = MINT_STLOC_NP_I4;
558                 } else if (mt == MINT_TYPE_O && !td->is_bb_start [td->in_start - td->il_code] && td->last_new_ip != NULL &&
559                         td->last_new_ip [0] == MINT_STLOC_O && td->last_new_ip [1] == offset) {
560                         td->last_new_ip [0] = MINT_STLOC_NP_O;
561                 } else {
562                         ADD_CODE(td, MINT_LDLOC_I1 + (mt - MINT_TYPE_I1));
563                         ADD_CODE(td, offset); /*FIX for large offset */
564                 }
565                 if (mt == MINT_TYPE_O)
566                         klass = mono_class_from_mono_type (type);
567         }
568         PUSH_TYPE(td, stack_type[mt], klass);
569 }
570
571 static void 
572 store_local(TransformData *td, int n)
573 {
574         MonoType *type = td->header->locals [n];
575         int mt = mint_type (type);
576         int offset = td->rtm->local_offsets [n];
577         CHECK_STACK (td, 1);
578 #if SIZEOF_VOID_P == 8
579         if (td->sp [-1].type == STACK_TYPE_I4 && stack_type [mt] == STACK_TYPE_I8) {
580                 ADD_CODE(td, MINT_CONV_I8_I4);
581                 td->sp [-1].type = STACK_TYPE_I8;
582         }
583 #endif
584         if (!can_store(td->sp [-1].type, stack_type [mt])) {
585                 g_warning("%s.%s: Store local stack type mismatch %d %d", 
586                         td->method->klass->name, td->method->name,
587                         stack_type [mt], td->sp [-1].type);
588         }
589         if (mt == MINT_TYPE_VT) {
590                 MonoClass *klass = mono_class_from_mono_type (type);
591                 gint32 size = mono_class_value_size (klass, NULL);
592                 ADD_CODE(td, MINT_STLOC_VT);
593                 ADD_CODE(td, offset); /*FIX for large offset */
594                 WRITE32(td, &size);
595                 if (td->sp [-1].type == STACK_TYPE_VT)
596                         POP_VT(td, size);
597         } else {
598                 g_assert (mt < MINT_TYPE_VT);
599                 ADD_CODE(td, MINT_STLOC_I1 + (mt - MINT_TYPE_I1));
600                 ADD_CODE(td, offset); /*FIX for large offset */
601         }
602         --td->sp;
603 }
604
605 #define SIMPLE_OP(td, op) \
606         do { \
607                 ADD_CODE(&td, op); \
608                 ++td.ip; \
609         } while (0)
610
611 static guint16
612 get_data_item_index (TransformData *td, void *ptr)
613 {
614         gpointer p = g_hash_table_lookup (td->data_hash, ptr);
615         guint index;
616         if (p != NULL)
617                 return GPOINTER_TO_UINT (p) - 1;
618         if (td->max_data_items == td->n_data_items) {
619                 td->max_data_items = td->n_data_items == 0 ? 16 : 2 * td->max_data_items;
620                 td->data_items = g_realloc (td->data_items, td->max_data_items * sizeof(td->data_items [0]));
621         }
622         index = td->n_data_items;
623         td->data_items [index] = ptr;
624         ++td->n_data_items;
625         g_hash_table_insert (td->data_hash, ptr, GUINT_TO_POINTER (index + 1));
626         return index;
627 }
628
629 static gboolean
630 jit_call_supported (MonoMethod *method, MonoMethodSignature *sig)
631 {
632         GSList *l;
633
634         if (sig->param_count > 6)
635                 return FALSE;
636         if (sig->pinvoke)
637                 return FALSE;
638         if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
639                 return FALSE;
640         if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
641                 return FALSE;
642         if (method->is_inflated)
643                 return FALSE;
644         if (method->string_ctor)
645                 return FALSE;
646
647         for (l = jit_classes; l; l = l->next) {
648                 char *class_name = l->data;
649                 // FIXME: Namespaces
650                 if (!strcmp (method->klass->name, class_name))
651                         return TRUE;
652         }
653
654         //return TRUE;
655         return FALSE;
656 }
657
658 static void
659 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)
660 {
661         MonoImage *image = method->klass->image;
662         MonoMethodSignature *csignature;
663         MonoError error;
664         int virtual = *td->ip == CEE_CALLVIRT;
665         int calli = *td->ip == CEE_CALLI || *td->ip == CEE_MONO_CALLI_EXTRA_ARG;
666         int i;
667         guint32 vt_stack_used = 0;
668         guint32 vt_res_size = 0;
669         int op = -1;
670         int native = 0;
671         int is_void = 0;
672
673         guint32 token = read32 (td->ip + 1);
674
675         if (target_method == NULL) {
676                 if (calli) {
677                         CHECK_STACK(td, 1);
678                         native = (method->wrapper_type != MONO_WRAPPER_DELEGATE_INVOKE && td->sp [-1].type == STACK_TYPE_I);
679                         --td->sp;
680                         if (method->wrapper_type != MONO_WRAPPER_NONE)
681                                 csignature = (MonoMethodSignature *)mono_method_get_wrapper_data (method, token);
682                         else
683                                 csignature = mono_metadata_parse_signature (image, token);
684
685                         if (generic_context) {
686                                 csignature = mono_inflate_generic_signature (csignature, generic_context, &error);
687                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
688                         }
689
690                         target_method = NULL;
691                 } else {
692                         if (method->wrapper_type == MONO_WRAPPER_NONE)
693                                 target_method = mono_get_method_full (image, token, NULL, generic_context);
694                         else
695                                 target_method = (MonoMethod *)mono_method_get_wrapper_data (method, token);
696                         csignature = mono_method_signature (target_method);
697                         if (target_method->klass == mono_defaults.string_class) {
698                                 if (target_method->name [0] == 'g') {
699                                         if (strcmp (target_method->name, "get_Chars") == 0)
700                                                 op = MINT_GETCHR;
701                                         else if (strcmp (target_method->name, "get_Length") == 0)
702                                                 op = MINT_STRLEN;
703                                 }
704                         } else if (mono_class_is_subclass_of (target_method->klass, mono_defaults.array_class, FALSE)) {
705                                 if (!strcmp (target_method->name, "get_Rank")) {
706                                         op = MINT_ARRAY_RANK;
707                                 } else if (!strcmp (target_method->name, "get_Length")) {
708                                         op = MINT_LDLEN;
709                                 } else if (!strcmp (target_method->name, "Address")) {
710                                         op = readonly ? MINT_LDELEMA : MINT_LDELEMA_TC;
711                                 }
712                         } else if (target_method && generic_context) {
713                                 csignature = mono_inflate_generic_signature (csignature, generic_context, &error);
714                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
715                                 target_method = mono_class_inflate_generic_method_checked (target_method, generic_context, &error);
716                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
717                         }
718                 }
719         } else {
720                 csignature = mono_method_signature (target_method);
721         }
722
723         if (constrained_class) {
724                 if (constrained_class->enumtype && !strcmp (target_method->name, "GetHashCode")) {
725                         /* Use the corresponding method from the base type to avoid boxing */
726                         MonoType *base_type = mono_class_enum_basetype (constrained_class);
727                         g_assert (base_type);
728                         constrained_class = mono_class_from_mono_type (base_type);
729                         target_method = mono_class_get_method_from_name (constrained_class, target_method->name, 0);
730                         g_assert (target_method);
731                 }
732         }
733
734         if (constrained_class) {
735                 mono_class_setup_vtable (constrained_class);
736 #if DEBUG_INTERP
737                 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);
738 #endif
739                 target_method = mono_get_method_constrained_with_method (image, target_method, constrained_class, generic_context, &error);
740 #if DEBUG_INTERP
741                 g_print ("                    : %s::%s.  %s (%p)\n", target_method->klass->name, target_method->name, mono_signature_full_name (target_method->signature), target_method);
742 #endif
743                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
744                 mono_class_setup_vtable (target_method->klass);
745
746                 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)) {
747                         if (target_method->klass == mono_defaults.enum_class && (td->sp - csignature->param_count - 1)->type == STACK_TYPE_MP) {
748                                 /* managed pointer on the stack, we need to deref that puppy */
749                                 ADD_CODE (td, MINT_LDIND_I);
750                                 ADD_CODE (td, csignature->param_count);
751                         }
752                         ADD_CODE (td, MINT_BOX);
753                         ADD_CODE (td, get_data_item_index (td, constrained_class));
754                         ADD_CODE (td, csignature->param_count);
755                 } else if (!constrained_class->valuetype) {
756                         /* managed pointer on the stack, we need to deref that puppy */
757                         ADD_CODE (td, MINT_LDIND_I);
758                         ADD_CODE (td, csignature->param_count);
759                 } else {
760                         if (target_method->klass->valuetype) {
761                                 /* Own method */
762                         } else {
763                                 /* Interface method */
764                                 int ioffset, slot;
765
766                                 mono_class_setup_vtable (constrained_class);
767                                 ioffset = mono_class_interface_offset (constrained_class, target_method->klass);
768                                 if (ioffset == -1)
769                                         g_error ("type load error: constrained_class");
770                                 slot = mono_method_get_vtable_slot (target_method);
771                                 if (slot == -1)
772                                         g_error ("type load error: target_method->klass");
773                                 target_method = constrained_class->vtable [ioffset + slot];
774
775                                 if (target_method->klass == mono_defaults.enum_class) {
776                                         if ((td->sp - csignature->param_count - 1)->type == STACK_TYPE_MP) {
777                                                 /* managed pointer on the stack, we need to deref that puppy */
778                                                 ADD_CODE (td, MINT_LDIND_I);
779                                                 ADD_CODE (td, csignature->param_count);
780                                         }
781                                         ADD_CODE (td, MINT_BOX);
782                                         ADD_CODE (td, get_data_item_index (td, constrained_class));
783                                         ADD_CODE (td, csignature->param_count);
784                                 }
785                         }
786                         virtual = FALSE;
787                 }
788         }
789
790         if (target_method)
791                 mono_class_init (target_method->klass);
792
793         CHECK_STACK (td, csignature->param_count + csignature->hasthis);
794         if (!calli && (!virtual || (target_method->flags & METHOD_ATTRIBUTE_VIRTUAL) == 0) &&
795                 (target_method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) == 0 && 
796                 (target_method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) == 0) {
797                 int called_inited = mono_class_vtable (domain, target_method->klass)->initialized;
798                 MonoMethodHeader *mheader = mono_method_get_header (target_method);
799
800                 if (/*mono_metadata_signature_equal (method->signature, target_method->signature) */ method == target_method && *(td->ip + 5) == CEE_RET) {
801                         int offset;
802                         if (mono_interp_traceopt)
803                                 g_print ("Optimize tail call of %s.%s\n", target_method->klass->name, target_method->name);
804
805                         for (i = csignature->param_count - 1 + !!csignature->hasthis; i >= 0; --i)
806                                 store_arg (td, i);
807
808                         ADD_CODE(td, MINT_BR_S);
809                         offset = body_start_offset - ((td->new_ip - 1) - td->new_code);
810                         ADD_CODE(td, offset);
811                         if (!is_bb_start [td->ip + 5 - td->il_code])
812                                 ++td->ip; /* gobble the CEE_RET if it isn't branched to */                              
813                         td->ip += 5;
814                         return;
815                 } else {
816                         /* mheader might not exist if this is a delegate invoc, etc */
817                         if (mheader && *mheader->code == CEE_RET && called_inited) {
818                                 if (mono_interp_traceopt)
819                                         g_print ("Inline (empty) call of %s.%s\n", target_method->klass->name, target_method->name);
820                                 for (i = 0; i < csignature->param_count; i++)
821                                         ADD_CODE (td, MINT_POP); /*FIX: vt */
822                                         ADD_CODE (td, 0);
823                                 if (csignature->hasthis) {
824                                         if (virtual)
825                                                 ADD_CODE(td, MINT_CKNULL);
826                                         ADD_CODE (td, MINT_POP);
827                                         ADD_CODE (td, 0);
828                                 }
829                                 td->sp -= csignature->param_count + csignature->hasthis;
830                                 td->ip += 5;
831                                 return;
832                         }
833                 }
834         }
835         if (method->wrapper_type == MONO_WRAPPER_NONE && target_method != NULL) {
836                 if (target_method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
837                         target_method = mono_marshal_get_native_wrapper (target_method, FALSE, FALSE);
838                 if (!virtual && target_method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
839                         target_method = mono_marshal_get_synchronized_wrapper (target_method);
840         }
841         g_assert (csignature->call_convention == MONO_CALL_DEFAULT || csignature->call_convention == MONO_CALL_C);
842         td->sp -= csignature->param_count + !!csignature->hasthis;
843         for (i = 0; i < csignature->param_count; ++i) {
844                 if (td->sp [i + !!csignature->hasthis].type == STACK_TYPE_VT) {
845                         gint32 size;
846                         MonoClass *klass = mono_class_from_mono_type (csignature->params [i]);
847                         if (csignature->pinvoke && method->wrapper_type != MONO_WRAPPER_NONE)
848                                 size = mono_class_native_size (klass, NULL);
849                         else
850                                 size = mono_class_value_size (klass, NULL);
851                         size = (size + 7) & ~7;
852                         vt_stack_used += size;
853                 }
854         }
855
856         /* need to handle typedbyref ... */
857         if (csignature->ret->type != MONO_TYPE_VOID) {
858                 int mt = mint_type(csignature->ret);
859                 MonoClass *klass = mono_class_from_mono_type (csignature->ret);
860                 if (mt == MINT_TYPE_VT) {
861                         if (csignature->pinvoke && method->wrapper_type != MONO_WRAPPER_NONE)
862                                 vt_res_size = mono_class_native_size (klass, NULL);
863                         else
864                                 vt_res_size = mono_class_value_size (klass, NULL);
865                         PUSH_VT(td, vt_res_size);
866                 }
867                 PUSH_TYPE(td, stack_type[mt], klass);
868         } else
869                 is_void = TRUE;
870
871         if (op >= 0) {
872                 ADD_CODE (td, op);
873 #if SIZEOF_VOID_P == 8
874                 if (op == MINT_LDLEN)
875                         ADD_CODE (td, MINT_CONV_I4_I8);
876 #endif
877                 if (op == MINT_LDELEMA || op == MINT_LDELEMA_TC) {
878                         ADD_CODE (td, get_data_item_index (td, target_method->klass));
879                         ADD_CODE (td, 1 + target_method->klass->rank);
880                 }
881         } else if (!calli && !virtual && jit_call_supported (target_method, csignature)) {
882                 ADD_CODE(td, MINT_JIT_CALL);
883                 ADD_CODE(td, get_data_item_index (td, (void *)mono_interp_get_runtime_method (domain, target_method, &error)));
884                 mono_error_assert_ok (&error);
885         } else {
886                 if (calli)
887                         ADD_CODE(td, native ? MINT_CALLI_NAT : MINT_CALLI);
888                 else if (virtual)
889                         ADD_CODE(td, is_void ? MINT_VCALLVIRT : MINT_CALLVIRT);
890                 else
891                         ADD_CODE(td, is_void ? MINT_VCALL : MINT_CALL);
892
893                 if (calli) {
894                         ADD_CODE(td, get_data_item_index (td, (void *)csignature));
895                 } else {
896                         ADD_CODE(td, get_data_item_index (td, (void *)mono_interp_get_runtime_method (domain, target_method, &error)));
897                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
898                 }
899         }
900         td->ip += 5;
901         if (vt_stack_used != 0 || vt_res_size != 0) {
902                 ADD_CODE(td, MINT_VTRESULT);
903                 ADD_CODE(td, vt_res_size);
904                 WRITE32(td, &vt_stack_used);
905                 td->vt_sp -= vt_stack_used;
906         }
907 }
908
909 static MonoClassField *
910 interp_field_from_token (MonoMethod *method, guint32 token, MonoClass **klass, MonoGenericContext *generic_context)
911 {
912         MonoClassField *field = NULL;
913         if (method->wrapper_type != MONO_WRAPPER_NONE) {
914                 field = (MonoClassField *) mono_method_get_wrapper_data (method, token);
915                 *klass = field->parent;
916         } else {
917                 MonoError error;
918                 error_init (&error);
919                 field = mono_field_from_token_checked (method->klass->image, token, klass, generic_context, &error);
920                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
921         }
922         return field;
923 }
924
925 static void
926 interp_save_debug_info (RuntimeMethod *rtm, MonoMethodHeader *header, TransformData *td, GArray *line_numbers)
927 {
928         MonoDebugMethodJitInfo *dinfo;
929         int i;
930
931         if (!mono_debug_enabled ())
932                 return;
933
934         /*
935          * We save the debug info in the same way the JIT does it, treating the interpreter IR as the native code.
936          */
937
938         dinfo = g_new0 (MonoDebugMethodJitInfo, 1);
939         dinfo->num_locals = header->num_locals;
940         dinfo->locals = g_new0 (MonoDebugVarInfo, header->num_locals);
941         dinfo->code_start = (guint8*)rtm->code;
942         dinfo->code_size = td->new_ip - td->new_code;
943         dinfo->epilogue_begin = 0;
944         dinfo->has_var_info = FALSE;
945         dinfo->num_line_numbers = line_numbers->len;
946         dinfo->line_numbers = g_new0 (MonoDebugLineNumberEntry, dinfo->num_line_numbers);
947         for (i = 0; i < dinfo->num_line_numbers; i++)
948                 dinfo->line_numbers [i] = g_array_index (line_numbers, MonoDebugLineNumberEntry, i);
949         mono_debug_add_method (rtm->method, dinfo, mono_domain_get ());
950
951         mono_debug_free_method_jit_info (dinfo);
952 }
953
954 static void
955 generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, MonoGenericContext *generic_context)
956 {
957         MonoMethodHeader *header = mono_method_get_header (method);
958         MonoMethodSignature *signature = mono_method_signature (method);
959         MonoImage *image = method->klass->image;
960         MonoDomain *domain = mono_domain_get ();
961         MonoClass *constrained_class = NULL;
962         MonoError error;
963         int offset, mt, i, i32;
964         gboolean readonly = FALSE;
965         MonoClass *klass;
966         MonoClassField *field;
967         const unsigned char *end;
968         int new_in_start_offset;
969         int body_start_offset;
970         int target;
971         guint32 token;
972         TransformData td;
973         int generating_code = 1;
974         GArray *line_numbers;
975
976         memset(&td, 0, sizeof(td));
977         td.method = method;
978         td.rtm = rtm;
979         td.is_bb_start = is_bb_start;
980         td.il_code = header->code;
981         td.code_size = header->code_size;
982         td.header = header;
983         td.max_code_size = td.code_size;
984         td.new_code = (unsigned short *)g_malloc(td.max_code_size * sizeof(gushort));
985         td.new_code_end = td.new_code + td.max_code_size;
986         td.in_offsets = g_malloc0(header->code_size * sizeof(int));
987         td.forward_refs = g_malloc(header->code_size * sizeof(int));
988         td.stack_state = g_malloc0(header->code_size * sizeof(StackInfo *));
989         td.stack_height = g_malloc(header->code_size * sizeof(int));
990         td.vt_stack_size = g_malloc(header->code_size * sizeof(int));
991         td.n_data_items = 0;
992         td.max_data_items = 0;
993         td.data_items = NULL;
994         td.data_hash = g_hash_table_new (NULL, NULL);
995         td.clause_indexes = g_malloc (header->code_size * sizeof (int));
996         rtm->data_items = td.data_items;
997         for (i = 0; i < header->code_size; i++) {
998                 td.forward_refs [i] = -1;
999                 td.stack_height [i] = -1;
1000                 td.clause_indexes [i] = -1;
1001         }
1002         td.new_ip = td.new_code;
1003         td.last_new_ip = NULL;
1004
1005         td.stack = g_malloc0 ((header->max_stack + 1) * sizeof (td.stack [0]));
1006         td.sp = td.stack;
1007         td.max_stack_height = 0;
1008
1009         line_numbers = g_array_new (FALSE, TRUE, sizeof (MonoDebugLineNumberEntry));
1010
1011         for (i = 0; i < header->num_clauses; i++) {
1012                 MonoExceptionClause *c = header->clauses + i;
1013                 td.stack_height [c->handler_offset] = 0;
1014                 td.vt_stack_size [c->handler_offset] = 0;
1015                 td.is_bb_start [c->handler_offset] = 1;
1016
1017                 td.stack_height [c->handler_offset] = 1;
1018                 td.stack_state [c->handler_offset] = g_malloc0(sizeof(StackInfo));
1019                 td.stack_state [c->handler_offset][0].type = STACK_TYPE_O;
1020                 td.stack_state [c->handler_offset][0].klass = NULL; /*FIX*/
1021
1022                 if (c->flags & MONO_EXCEPTION_CLAUSE_FILTER) {
1023                         td.stack_height [c->data.filter_offset] = 0;
1024                         td.vt_stack_size [c->data.filter_offset] = 0;
1025                         td.is_bb_start [c->data.filter_offset] = 1;
1026
1027                         td.stack_height [c->data.filter_offset] = 1;
1028                         td.stack_state [c->data.filter_offset] = g_malloc0(sizeof(StackInfo));
1029                         td.stack_state [c->data.filter_offset][0].type = STACK_TYPE_O;
1030                         td.stack_state [c->data.filter_offset][0].klass = NULL; /*FIX*/
1031                 }
1032
1033                 if ((c->flags & MONO_EXCEPTION_CLAUSE_FINALLY) || (c->flags & MONO_EXCEPTION_CLAUSE_FAULT)) {
1034                         for (int j = c->handler_offset; j < c->handler_offset + c->handler_len; ++j) {
1035                                 if (td.clause_indexes [j] == -1)
1036                                         td.clause_indexes [j] = i;
1037                         }
1038                 }
1039         }
1040
1041         td.ip = header->code;
1042         end = td.ip + header->code_size;
1043
1044         if (mono_interp_traceopt) {
1045                 char *tmp = mono_disasm_code (NULL, method, td.ip, end);
1046                 char *name = mono_method_full_name (method, TRUE);
1047                 g_print ("Method %s, original code:\n", name);
1048                 g_print ("%s\n", tmp);
1049                 g_free (tmp);
1050                 g_free (name);
1051         }
1052
1053         if (signature->hasthis)
1054                 store_inarg (&td, 0);
1055         for (i = 0; i < signature->param_count; i++)
1056                 store_inarg (&td, i + !!signature->hasthis);
1057
1058         body_start_offset = td.new_ip - td.new_code;
1059
1060         for (i = 0; i < header->num_locals; i++) {
1061                 int mt = mint_type(header->locals [i]);
1062                 if (mt == MINT_TYPE_VT || mt == MINT_TYPE_O || mt == MINT_TYPE_P) {
1063                         ADD_CODE(&td, MINT_INITLOCALS);
1064                         break;
1065                 }
1066         }
1067
1068         while (td.ip < end) {
1069                 int in_offset;
1070
1071                 g_assert (td.sp >= td.stack);
1072                 g_assert (td.vt_sp < 0x10000000);
1073                 in_offset = td.ip - header->code;
1074                 td.in_offsets [in_offset] = td.new_ip - td.new_code;
1075                 new_in_start_offset = td.new_ip - td.new_code;
1076                 td.in_start = td.ip;
1077
1078                 MonoDebugLineNumberEntry lne;
1079                 lne.native_offset = td.new_ip - td.new_code;
1080                 lne.il_offset = td.ip - header->code;
1081                 g_array_append_val (line_numbers, lne);
1082
1083                 while (td.forward_refs [in_offset] >= 0) {
1084                         int j = td.forward_refs [in_offset];
1085                         int slot;
1086                         td.forward_refs [in_offset] = td.forward_refs [j];
1087                         if (td.in_offsets [j] < 0) {                        
1088                                 int old_switch_offset = -td.in_offsets [j];
1089                                 int new_switch_offset = td.in_offsets [old_switch_offset];
1090                                 int switch_case = (j - old_switch_offset - 5) / 4;
1091                                 int n_cases = read32 (header->code + old_switch_offset + 1);
1092                                 offset = (td.new_ip - td.new_code) - (new_switch_offset + 2 * n_cases + 3);
1093                                 slot = new_switch_offset + 3 + 2 * switch_case;
1094                                 td.new_code [slot] = * (unsigned short *)(&offset);
1095                                 td.new_code [slot + 1] = * ((unsigned short *)&offset + 1);
1096                         } else {
1097                                 int op = td.new_code [td.in_offsets [j]];
1098                                 if (mono_interp_opargtype [op] == MintOpShortBranch) {
1099                                         offset = (td.new_ip - td.new_code) - td.in_offsets [j];
1100                                         g_assert (offset <= 32767);
1101                                         slot = td.in_offsets [j] + 1;
1102                                         td.new_code [slot] = offset;
1103                                 } else {
1104                                         offset = (td.new_ip - td.new_code) - td.in_offsets [j];
1105                                         slot = td.in_offsets [j] + 1;
1106                                         td.new_code [slot] = * (unsigned short *)(&offset);
1107                                         td.new_code [slot + 1] = * ((unsigned short *)&offset + 1);
1108                                 }
1109                         }
1110                 }
1111                 if (td.stack_height [in_offset] >= 0) {
1112                         g_assert (is_bb_start [in_offset]);
1113                         if (td.stack_height [in_offset] > 0)
1114                                 memcpy (td.stack, td.stack_state [in_offset], td.stack_height [in_offset] * sizeof(td.stack [0]));
1115                         td.sp = td.stack + td.stack_height [in_offset];
1116                         td.vt_sp = td.vt_stack_size [in_offset];
1117                 }
1118                 if (is_bb_start [in_offset]) {
1119                         generating_code = 1;
1120                 }
1121                 if (!generating_code) {
1122                         while (td.ip < end && !is_bb_start [td.ip - td.il_code])
1123                                 ++td.ip;
1124                         continue;
1125                 }
1126                 if (mono_interp_traceopt > 1) {
1127                         printf("IL_%04lx %s %-10s -> IL_%04lx, sp %ld, %s %-12s vt_sp %u (max %u)\n", 
1128                                 td.ip - td.il_code,
1129                                 td.is_bb_start [td.ip - td.il_code] == 3 ? "<>" :
1130                                 td.is_bb_start [td.ip - td.il_code] == 2 ? "< " :
1131                                 td.is_bb_start [td.ip - td.il_code] == 1 ? " >" : "  ",
1132                                 mono_opcode_name (*td.ip), td.new_ip - td.new_code, td.sp - td.stack, 
1133                                 td.sp > td.stack ? stack_type_string [td.sp [-1].type] : "  ",
1134                                 (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) : "",
1135                                 td.vt_sp, td.max_vt_sp);
1136                 }
1137                 switch (*td.ip) {
1138                 case CEE_NOP: 
1139                         /* lose it */
1140                         ++td.ip;
1141                         break;
1142                 case CEE_BREAK:
1143                         SIMPLE_OP(td, MINT_BREAK);
1144                         break;
1145                 case CEE_LDARG_0:
1146                 case CEE_LDARG_1:
1147                 case CEE_LDARG_2:
1148                 case CEE_LDARG_3:
1149                         load_arg (&td, *td.ip - CEE_LDARG_0);
1150                         ++td.ip;
1151                         break;
1152                 case CEE_LDLOC_0:
1153                 case CEE_LDLOC_1:
1154                 case CEE_LDLOC_2:
1155                 case CEE_LDLOC_3:
1156                         load_local (&td, *td.ip - CEE_LDLOC_0);
1157                         ++td.ip;
1158                         break;
1159                 case CEE_STLOC_0:
1160                 case CEE_STLOC_1:
1161                 case CEE_STLOC_2:
1162                 case CEE_STLOC_3:
1163                         store_local (&td, *td.ip - CEE_STLOC_0);
1164                         ++td.ip;
1165                         break;
1166                 case CEE_LDARG_S:
1167                         load_arg (&td, ((guint8 *)td.ip)[1]);
1168                         td.ip += 2;
1169                         break;
1170                 case CEE_LDARGA_S: {
1171                         /* NOTE: n includes this */
1172                         int n = ((guint8 *) td.ip) [1];
1173                         ADD_CODE (&td, MINT_LDARGA);
1174                         ADD_CODE (&td, td.rtm->arg_offsets [n]);
1175                         PUSH_SIMPLE_TYPE(&td, STACK_TYPE_MP);
1176                         td.ip += 2;
1177                         break;
1178                 }
1179                 case CEE_STARG_S:
1180                         store_arg (&td, ((guint8 *)td.ip)[1]);
1181                         td.ip += 2;
1182                         break;
1183                 case CEE_LDLOC_S:
1184                         load_local (&td, ((guint8 *)td.ip)[1]);
1185                         td.ip += 2;
1186                         break;
1187                 case CEE_LDLOCA_S:
1188                         ADD_CODE(&td, MINT_LDLOCA_S);
1189                         ADD_CODE(&td, td.rtm->local_offsets [((guint8 *)td.ip)[1]]);
1190                         PUSH_SIMPLE_TYPE(&td, STACK_TYPE_MP);
1191                         td.ip += 2;
1192                         break;
1193                 case CEE_STLOC_S:
1194                         store_local (&td, ((guint8 *)td.ip)[1]);
1195                         td.ip += 2;
1196                         break;
1197                 case CEE_LDNULL: 
1198                         SIMPLE_OP(td, MINT_LDNULL);
1199                         PUSH_TYPE(&td, STACK_TYPE_O, NULL);
1200                         break;
1201                 case CEE_LDC_I4_M1:
1202                         SIMPLE_OP(td, MINT_LDC_I4_M1);
1203                         PUSH_SIMPLE_TYPE(&td, STACK_TYPE_I4);
1204                         break;
1205                 case CEE_LDC_I4_0:
1206                         if (!td.is_bb_start[td.ip + 1 - td.il_code] && td.ip [1] == 0xfe && td.ip [2] == CEE_CEQ && 
1207                                 td.sp > td.stack && td.sp [-1].type == STACK_TYPE_I4) {
1208                                 SIMPLE_OP(td, MINT_CEQ0_I4);
1209                                 td.ip += 2;
1210                         } else {
1211                                 SIMPLE_OP(td, MINT_LDC_I4_0);
1212                                 PUSH_SIMPLE_TYPE(&td, STACK_TYPE_I4);
1213                         }
1214                         break;
1215                 case CEE_LDC_I4_1:
1216                         if (!td.is_bb_start[td.ip + 1 - td.il_code] && 
1217                                 (td.ip [1] == CEE_ADD || td.ip [1] == CEE_SUB) && td.sp [-1].type == STACK_TYPE_I4) {
1218                                 ADD_CODE(&td, td.ip [1] == CEE_ADD ? MINT_ADD1_I4 : MINT_SUB1_I4);
1219                                 td.ip += 2;
1220                         } else {
1221                                 SIMPLE_OP(td, MINT_LDC_I4_1);
1222                                 PUSH_SIMPLE_TYPE(&td, STACK_TYPE_I4);
1223                         }
1224                         break;
1225                 case CEE_LDC_I4_2:
1226                 case CEE_LDC_I4_3:
1227                 case CEE_LDC_I4_4:
1228                 case CEE_LDC_I4_5:
1229                 case CEE_LDC_I4_6:
1230                 case CEE_LDC_I4_7:
1231                 case CEE_LDC_I4_8:
1232                         SIMPLE_OP(td, (*td.ip - CEE_LDC_I4_0) + MINT_LDC_I4_0);
1233                         PUSH_SIMPLE_TYPE(&td, STACK_TYPE_I4);
1234                         break;
1235                 case CEE_LDC_I4_S: 
1236                         ADD_CODE(&td, MINT_LDC_I4_S);
1237                         ADD_CODE(&td, ((gint8 *) td.ip) [1]);
1238                         td.ip += 2;
1239                         PUSH_SIMPLE_TYPE(&td, STACK_TYPE_I4);
1240                         break;
1241                 case CEE_LDC_I4:
1242                         i32 = read32 (td.ip + 1);
1243                         ADD_CODE(&td, MINT_LDC_I4);
1244                         WRITE32(&td, &i32);
1245                         td.ip += 5;
1246                         PUSH_SIMPLE_TYPE(&td, STACK_TYPE_I4);
1247                         break;
1248                 case CEE_LDC_I8: {
1249                         gint64 val = read64 (td.ip + 1);
1250                         ADD_CODE(&td, MINT_LDC_I8);
1251                         WRITE64(&td, &val);
1252                         td.ip += 9;
1253                         PUSH_SIMPLE_TYPE(&td, STACK_TYPE_I8);
1254                         break;
1255                 }
1256                 case CEE_LDC_R4: {
1257                         float val;
1258                         readr4 (td.ip + 1, &val);
1259                         ADD_CODE(&td, MINT_LDC_R4);
1260                         WRITE32(&td, &val);
1261                         td.ip += 5;
1262                         PUSH_SIMPLE_TYPE(&td, STACK_TYPE_R8);
1263                         break;
1264                 }
1265                 case CEE_LDC_R8: {
1266                         double val;
1267                         readr8 (td.ip + 1, &val);
1268                         ADD_CODE(&td, MINT_LDC_R8);
1269                         WRITE64(&td, &val);
1270                         td.ip += 9;
1271                         PUSH_SIMPLE_TYPE(&td, STACK_TYPE_R8);
1272                         break;
1273                 }
1274                 case CEE_DUP: {
1275                         int type = td.sp [-1].type;
1276                         MonoClass *klass = td.sp [-1].klass;
1277                         if (td.sp [-1].type == STACK_TYPE_VT) {
1278                                 gint32 size = mono_class_value_size (klass, NULL);
1279                                 PUSH_VT(&td, size);
1280                                 ADD_CODE(&td, MINT_DUP_VT);
1281                                 WRITE32(&td, &size);
1282                                 td.ip ++;
1283                         } else 
1284                                 SIMPLE_OP(td, MINT_DUP);
1285                         PUSH_TYPE(&td, type, klass);
1286                         break;
1287                 }
1288                 case CEE_POP:
1289                         CHECK_STACK(&td, 1);
1290                         SIMPLE_OP(td, MINT_POP);
1291                         ADD_CODE (&td, 0);
1292                         if (td.sp [-1].type == STACK_TYPE_VT) {
1293                                 int size = mono_class_value_size (td.sp [-1].klass, NULL);
1294                                 size = (size + 7) & ~7;
1295                                 ADD_CODE(&td, MINT_VTRESULT);
1296                                 ADD_CODE(&td, 0);
1297                                 WRITE32(&td, &size);
1298                                 td.vt_sp -= size;
1299                         }
1300                         --td.sp;
1301                         break;
1302                 case CEE_JMP: {
1303                         MonoMethod *m;
1304                         if (td.sp > td.stack)
1305                                 g_warning ("CEE_JMP: stack must be empty");
1306                         token = read32 (td.ip + 1);
1307                         m = mono_get_method_full (image, token, NULL, generic_context);
1308                         ADD_CODE (&td, MINT_JMP);
1309                         ADD_CODE (&td, get_data_item_index (&td, mono_interp_get_runtime_method (domain, m, &error)));
1310                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
1311                         td.ip += 5;
1312                         break;
1313                 }
1314                 case CEE_CALLVIRT: /* Fall through */
1315                 case CEE_CALLI:    /* Fall through */
1316                 case CEE_CALL: {
1317                         interp_transform_call (&td, method, NULL, domain, generic_context, is_bb_start, body_start_offset, constrained_class, readonly);
1318                         constrained_class = NULL;
1319                         readonly = FALSE;
1320                         break;
1321                 }
1322                 case CEE_RET: {
1323                         int vt_size = 0;
1324                         if (signature->ret->type != MONO_TYPE_VOID) {
1325                                 --td.sp;
1326                                 MonoClass *klass = mono_class_from_mono_type (signature->ret);
1327                                 if (mint_type (&klass->byval_arg) == MINT_TYPE_VT) {
1328                                         vt_size = mono_class_value_size (klass, NULL);
1329                                         vt_size = (vt_size + 7) & ~7;
1330                                 }
1331                         }
1332                         if (td.sp > td.stack)
1333                                 g_warning ("%s.%s: CEE_RET: more values on stack: %d", td.method->klass->name, td.method->name, td.sp - td.stack);
1334                         if (td.vt_sp != vt_size)
1335                                 g_error ("%s.%s: CEE_RET: value type stack: %d vs. %d", td.method->klass->name, td.method->name, td.vt_sp, vt_size);
1336                         if (vt_size == 0)
1337                                 SIMPLE_OP(td, signature->ret->type == MONO_TYPE_VOID ? MINT_RET_VOID : MINT_RET);
1338                         else {
1339                                 ADD_CODE(&td, MINT_RET_VT);
1340                                 WRITE32(&td, &vt_size);
1341                                 ++td.ip;
1342                         }
1343                         generating_code = 0;
1344                         break;
1345                 }
1346                 case CEE_BR:
1347                         handle_branch (&td, MINT_BR_S, MINT_BR, 5 + read32 (td.ip + 1));
1348                         td.ip += 5;
1349                         generating_code = 0;
1350                         break;
1351                 case CEE_BR_S:
1352                         handle_branch (&td, MINT_BR_S, MINT_BR, 2 + (gint8)td.ip [1]);
1353                         td.ip += 2;
1354                         generating_code = 0;
1355                         break;
1356                 case CEE_BRFALSE:
1357                         one_arg_branch (&td, MINT_BRFALSE_I4, 5 + read32 (td.ip + 1));
1358                         td.ip += 5;
1359                         break;
1360                 case CEE_BRFALSE_S:
1361                         one_arg_branch (&td, MINT_BRFALSE_I4, 2 + (gint8)td.ip [1]);
1362                         td.ip += 2;
1363                         break;
1364                 case CEE_BRTRUE:
1365                         one_arg_branch (&td, MINT_BRTRUE_I4, 5 + read32 (td.ip + 1));
1366                         td.ip += 5;
1367                         break;
1368                 case CEE_BRTRUE_S:
1369                         one_arg_branch (&td, MINT_BRTRUE_I4, 2 + (gint8)td.ip [1]);
1370                         td.ip += 2;
1371                         break;
1372                 case CEE_BEQ:
1373                         two_arg_branch (&td, MINT_BEQ_I4, 5 + read32 (td.ip + 1));
1374                         td.ip += 5;
1375                         break;
1376                 case CEE_BEQ_S:
1377                         two_arg_branch (&td, MINT_BEQ_I4, 2 + (gint8) td.ip [1]);
1378                         td.ip += 2;
1379                         break;
1380                 case CEE_BGE:
1381                         two_arg_branch (&td, MINT_BGE_I4, 5 + read32 (td.ip + 1));
1382                         td.ip += 5;
1383                         break;
1384                 case CEE_BGE_S:
1385                         two_arg_branch (&td, MINT_BGE_I4, 2 + (gint8) td.ip [1]);
1386                         td.ip += 2;
1387                         break;
1388                 case CEE_BGT:
1389                         two_arg_branch (&td, MINT_BGT_I4, 5 + read32 (td.ip + 1));
1390                         td.ip += 5;
1391                         break;
1392                 case CEE_BGT_S:
1393                         two_arg_branch (&td, MINT_BGT_I4, 2 + (gint8) td.ip [1]);
1394                         td.ip += 2;
1395                         break;
1396                 case CEE_BLT:
1397                         two_arg_branch (&td, MINT_BLT_I4, 5 + read32 (td.ip + 1));
1398                         td.ip += 5;
1399                         break;
1400                 case CEE_BLT_S:
1401                         two_arg_branch (&td, MINT_BLT_I4, 2 + (gint8) td.ip [1]);
1402                         td.ip += 2;
1403                         break;
1404                 case CEE_BLE:
1405                         two_arg_branch (&td, MINT_BLE_I4, 5 + read32 (td.ip + 1));
1406                         td.ip += 5;
1407                         break;
1408                 case CEE_BLE_S:
1409                         two_arg_branch (&td, MINT_BLE_I4, 2 + (gint8) td.ip [1]);
1410                         td.ip += 2;
1411                         break;
1412                 case CEE_BNE_UN:
1413                         two_arg_branch (&td, MINT_BNE_UN_I4, 5 + read32 (td.ip + 1));
1414                         td.ip += 5;
1415                         break;
1416                 case CEE_BNE_UN_S:
1417                         two_arg_branch (&td, MINT_BNE_UN_I4, 2 + (gint8) td.ip [1]);
1418                         td.ip += 2;
1419                         break;
1420                 case CEE_BGE_UN:
1421                         two_arg_branch (&td, MINT_BGE_UN_I4, 5 + read32 (td.ip + 1));
1422                         td.ip += 5;
1423                         break;
1424                 case CEE_BGE_UN_S:
1425                         two_arg_branch (&td, MINT_BGE_UN_I4, 2 + (gint8) td.ip [1]);
1426                         td.ip += 2;
1427                         break;
1428                 case CEE_BGT_UN:
1429                         two_arg_branch (&td, MINT_BGT_UN_I4, 5 + read32 (td.ip + 1));
1430                         td.ip += 5;
1431                         break;
1432                 case CEE_BGT_UN_S:
1433                         two_arg_branch (&td, MINT_BGT_UN_I4, 2 + (gint8) td.ip [1]);
1434                         td.ip += 2;
1435                         break;
1436                 case CEE_BLE_UN:
1437                         two_arg_branch (&td, MINT_BLE_UN_I4, 5 + read32 (td.ip + 1));
1438                         td.ip += 5;
1439                         break;
1440                 case CEE_BLE_UN_S:
1441                         two_arg_branch (&td, MINT_BLE_UN_I4, 2 + (gint8) td.ip [1]);
1442                         td.ip += 2;
1443                         break;
1444                 case CEE_BLT_UN:
1445                         two_arg_branch (&td, MINT_BLT_UN_I4, 5 + read32 (td.ip + 1));
1446                         td.ip += 5;
1447                         break;
1448                 case CEE_BLT_UN_S:
1449                         two_arg_branch (&td, MINT_BLT_UN_I4, 2 + (gint8) td.ip [1]);
1450                         td.ip += 2;
1451                         break;
1452                 case CEE_SWITCH: {
1453                         guint32 n;
1454                         const unsigned char *next_ip;
1455                         const unsigned char *base_ip = td.ip;
1456                         unsigned short *next_new_ip;
1457                         ++td.ip;
1458                         n = read32 (td.ip);
1459                         ADD_CODE (&td, MINT_SWITCH);
1460                         WRITE32 (&td, &n);
1461                         td.ip += 4;
1462                         next_ip = td.ip + n * 4;
1463                         next_new_ip = td.new_ip + n * 2;
1464                         --td.sp;
1465                         int stack_height = td.sp - td.stack;
1466                         for (i = 0; i < n; i++) {
1467                                 offset = read32 (td.ip);
1468                                 target = next_ip - td.il_code + offset;
1469                                 if (offset < 0) {
1470 #if DEBUG_INTERP
1471                                         if (stack_height > 0 && stack_height != td.stack_height [target])
1472                                                 g_warning ("SWITCH with back branch and non-empty stack");
1473 #endif
1474                                         target = td.in_offsets [target] - (next_new_ip - td.new_code);
1475                                 } else {
1476                                         td.stack_height [target] = stack_height;
1477                                         td.vt_stack_size [target] = td.vt_sp;
1478                                         if (stack_height > 0)
1479                                                 td.stack_state [target] = g_memdup (td.stack, stack_height * sizeof (td.stack [0]));
1480                                         int prev = td.forward_refs [target];
1481                                         td.forward_refs [td.ip - td.il_code] = prev;
1482                                         td.forward_refs [target] = td.ip - td.il_code;
1483                                         td.in_offsets [td.ip - td.il_code] = - (base_ip - td.il_code);
1484                                 }
1485                                 WRITE32 (&td, &target);
1486                                 td.ip += 4;
1487                         }
1488                         break;
1489                 }
1490                 case CEE_LDIND_I1:
1491                         CHECK_STACK (&td, 1);
1492                         SIMPLE_OP (td, MINT_LDIND_I1);
1493                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
1494                         break;
1495                 case CEE_LDIND_U1:
1496                         CHECK_STACK (&td, 1);
1497                         SIMPLE_OP (td, MINT_LDIND_U1);
1498                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
1499                         break;
1500                 case CEE_LDIND_I2:
1501                         CHECK_STACK (&td, 1);
1502                         SIMPLE_OP (td, MINT_LDIND_I2);
1503                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
1504                         break;
1505                 case CEE_LDIND_U2:
1506                         CHECK_STACK (&td, 1);
1507                         SIMPLE_OP (td, MINT_LDIND_U2);
1508                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
1509                         break;
1510                 case CEE_LDIND_I4:
1511                         CHECK_STACK (&td, 1);
1512                         SIMPLE_OP (td, MINT_LDIND_I4);
1513                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
1514                         break;
1515                 case CEE_LDIND_U4:
1516                         CHECK_STACK (&td, 1);
1517                         SIMPLE_OP (td, MINT_LDIND_U4);
1518                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
1519                         break;
1520                 case CEE_LDIND_I8:
1521                         CHECK_STACK (&td, 1);
1522                         SIMPLE_OP (td, MINT_LDIND_I8);
1523                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I8);
1524                         break;
1525                 case CEE_LDIND_I:
1526                         CHECK_STACK (&td, 1);
1527                         SIMPLE_OP (td, MINT_LDIND_I);
1528                         ADD_CODE (&td, 0);
1529                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I);
1530                         break;
1531                 case CEE_LDIND_R4:
1532                         CHECK_STACK (&td, 1);
1533                         SIMPLE_OP (td, MINT_LDIND_R4);
1534                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_R8);
1535                         break;
1536                 case CEE_LDIND_R8:
1537                         CHECK_STACK (&td, 1);
1538                         SIMPLE_OP (td, MINT_LDIND_R8);
1539                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_R8);
1540                         break;
1541                 case CEE_LDIND_REF:
1542                         CHECK_STACK (&td, 1);
1543                         SIMPLE_OP (td, MINT_LDIND_REF);
1544                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_O);
1545                         break;
1546                 case CEE_STIND_REF:
1547                         CHECK_STACK (&td, 2);
1548                         SIMPLE_OP (td, MINT_STIND_REF);
1549                         td.sp -= 2;
1550                         break;
1551                 case CEE_STIND_I1:
1552                         CHECK_STACK (&td, 2);
1553                         SIMPLE_OP (td, MINT_STIND_I1);
1554                         td.sp -= 2;
1555                         break;
1556                 case CEE_STIND_I2:
1557                         CHECK_STACK (&td, 2);
1558                         SIMPLE_OP (td, MINT_STIND_I2);
1559                         td.sp -= 2;
1560                         break;
1561                 case CEE_STIND_I4:
1562                         CHECK_STACK (&td, 2);
1563                         SIMPLE_OP (td, MINT_STIND_I4);
1564                         td.sp -= 2;
1565                         break;
1566                 case CEE_STIND_I:
1567                         CHECK_STACK (&td, 2);
1568                         SIMPLE_OP (td, MINT_STIND_I);
1569                         td.sp -= 2;
1570                         break;
1571                 case CEE_STIND_I8:
1572                         CHECK_STACK (&td, 2);
1573                         SIMPLE_OP (td, MINT_STIND_I8);
1574                         td.sp -= 2;
1575                         break;
1576                 case CEE_STIND_R4:
1577                         CHECK_STACK (&td, 2);
1578                         SIMPLE_OP (td, MINT_STIND_R4);
1579                         td.sp -= 2;
1580                         break;
1581                 case CEE_STIND_R8:
1582                         CHECK_STACK (&td, 2);
1583                         SIMPLE_OP (td, MINT_STIND_R8);
1584                         td.sp -= 2;
1585                         break;
1586                 case CEE_ADD:
1587                         binary_arith_op(&td, MINT_ADD_I4);
1588                         ++td.ip;
1589                         break;
1590                 case CEE_SUB:
1591                         binary_arith_op(&td, MINT_SUB_I4);
1592                         ++td.ip;
1593                         break;
1594                 case CEE_MUL:
1595                         binary_arith_op(&td, MINT_MUL_I4);
1596                         ++td.ip;
1597                         break;
1598                 case CEE_DIV:
1599                         binary_arith_op(&td, MINT_DIV_I4);
1600                         ++td.ip;
1601                         break;
1602                 case CEE_DIV_UN:
1603                         binary_arith_op(&td, MINT_DIV_UN_I4);
1604                         ++td.ip;
1605                         break;
1606                 case CEE_REM:
1607                         binary_arith_op (&td, MINT_REM_I4);
1608                         ++td.ip;
1609                         break;
1610                 case CEE_REM_UN:
1611                         binary_arith_op (&td, MINT_REM_UN_I4);
1612                         ++td.ip;
1613                         break;
1614                 case CEE_AND:
1615                         binary_arith_op (&td, MINT_AND_I4);
1616                         ++td.ip;
1617                         break;
1618                 case CEE_OR:
1619                         binary_arith_op (&td, MINT_OR_I4);
1620                         ++td.ip;
1621                         break;
1622                 case CEE_XOR:
1623                         binary_arith_op (&td, MINT_XOR_I4);
1624                         ++td.ip;
1625                         break;
1626                 case CEE_SHL:
1627                         shift_op (&td, MINT_SHL_I4);
1628                         ++td.ip;
1629                         break;
1630                 case CEE_SHR:
1631                         shift_op (&td, MINT_SHR_I4);
1632                         ++td.ip;
1633                         break;
1634                 case CEE_SHR_UN:
1635                         shift_op (&td, MINT_SHR_UN_I4);
1636                         ++td.ip;
1637                         break;
1638                 case CEE_NEG:
1639                         unary_arith_op (&td, MINT_NEG_I4);
1640                         ++td.ip;
1641                         break;
1642                 case CEE_NOT:
1643                         unary_arith_op (&td, MINT_NOT_I4);
1644                         ++td.ip;
1645                         break;
1646                 case CEE_CONV_U1:
1647                         CHECK_STACK (&td, 1);
1648                         switch (td.sp [-1].type) {
1649                         case STACK_TYPE_R8:
1650                                 ADD_CODE(&td, MINT_CONV_U1_R8);
1651                                 break;
1652                         case STACK_TYPE_I4:
1653                                 ADD_CODE(&td, MINT_CONV_U1_I4);
1654                                 break;
1655                         case STACK_TYPE_I8:
1656                                 ADD_CODE(&td, MINT_CONV_U1_I8);
1657                                 break;
1658                         default:
1659                                 g_assert_not_reached ();
1660                         }
1661                         ++td.ip;
1662                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
1663                         break;
1664                 case CEE_CONV_I1:
1665                         CHECK_STACK (&td, 1);
1666                         switch (td.sp [-1].type) {
1667                         case STACK_TYPE_R8:
1668                                 ADD_CODE(&td, MINT_CONV_I1_R8);
1669                                 break;
1670                         case STACK_TYPE_I4:
1671                                 ADD_CODE(&td, MINT_CONV_I1_I4);
1672                                 break;
1673                         case STACK_TYPE_I8:
1674                                 ADD_CODE(&td, MINT_CONV_I1_I8);
1675                                 break;
1676                         default:
1677                                 g_assert_not_reached ();
1678                         }
1679                         ++td.ip;
1680                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
1681                         break;
1682                 case CEE_CONV_U2:
1683                         CHECK_STACK (&td, 1);
1684                         switch (td.sp [-1].type) {
1685                         case STACK_TYPE_R8:
1686                                 ADD_CODE(&td, MINT_CONV_U2_R8);
1687                                 break;
1688                         case STACK_TYPE_I4:
1689                                 ADD_CODE(&td, MINT_CONV_U2_I4);
1690                                 break;
1691                         case STACK_TYPE_I8:
1692                                 ADD_CODE(&td, MINT_CONV_U2_I8);
1693                                 break;
1694                         default:
1695                                 g_assert_not_reached ();
1696                         }
1697                         ++td.ip;
1698                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
1699                         break;
1700                 case CEE_CONV_I2:
1701                         CHECK_STACK (&td, 1);
1702                         switch (td.sp [-1].type) {
1703                         case STACK_TYPE_R8:
1704                                 ADD_CODE(&td, MINT_CONV_I2_R8);
1705                                 break;
1706                         case STACK_TYPE_I4:
1707                                 ADD_CODE(&td, MINT_CONV_I2_I4);
1708                                 break;
1709                         case STACK_TYPE_I8:
1710                                 ADD_CODE(&td, MINT_CONV_I2_I8);
1711                                 break;
1712                         default:
1713                                 g_assert_not_reached ();
1714                         }
1715                         ++td.ip;
1716                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
1717                         break;
1718                 case CEE_CONV_U:
1719                         CHECK_STACK (&td, 1);
1720                         switch (td.sp [-1].type) {
1721                         case STACK_TYPE_R8:
1722 #if SIZEOF_VOID_P == 4
1723                                 ADD_CODE(&td, MINT_CONV_U4_R8);
1724 #else
1725                                 ADD_CODE(&td, MINT_CONV_U8_R8);
1726 #endif
1727                                 break;
1728                         case STACK_TYPE_I4:
1729 #if SIZEOF_VOID_P == 8
1730                                 ADD_CODE(&td, MINT_CONV_U8_I4);
1731 #endif
1732                                 break;
1733                         case STACK_TYPE_I8:
1734 #if SIZEOF_VOID_P == 4
1735                                 ADD_CODE(&td, MINT_CONV_U4_I8);
1736 #endif
1737                                 break;
1738                         case STACK_TYPE_MP:
1739                                 break;
1740                         default:
1741                                 g_assert_not_reached ();
1742                         }
1743                         ++td.ip;
1744                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I);
1745                         break;
1746                 case CEE_CONV_I: 
1747                         CHECK_STACK (&td, 1);
1748                         switch (td.sp [-1].type) {
1749                         case STACK_TYPE_R8:
1750 #if SIZEOF_VOID_P == 8
1751                                 ADD_CODE(&td, MINT_CONV_I8_R8);
1752 #else
1753                                 ADD_CODE(&td, MINT_CONV_I4_R8);
1754 #endif
1755                                 break;
1756                         case STACK_TYPE_I4:
1757 #if SIZEOF_VOID_P == 8
1758                                 ADD_CODE(&td, MINT_CONV_I8_I4);
1759 #endif
1760                                 break;
1761                         case STACK_TYPE_O:
1762                                 break;
1763                         case STACK_TYPE_MP:
1764                                 break;
1765                         case STACK_TYPE_I8:
1766 #if SIZEOF_VOID_P == 4
1767                                 ADD_CODE(&td, MINT_CONV_I4_I8);
1768 #endif
1769                                 break;
1770                         default:
1771                                 g_assert_not_reached ();
1772                         }
1773                         ++td.ip;
1774                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I);
1775                         break;
1776                 case CEE_CONV_U4:
1777                         CHECK_STACK (&td, 1);
1778                         switch (td.sp [-1].type) {
1779                         case STACK_TYPE_R8:
1780                                 ADD_CODE(&td, MINT_CONV_U4_R8);
1781                                 break;
1782                         case STACK_TYPE_I4:
1783                                 break;
1784                         case STACK_TYPE_I8:
1785                                 ADD_CODE(&td, MINT_CONV_U4_I8);
1786                                 break;
1787                         case STACK_TYPE_MP:
1788 #if SIZEOF_VOID_P == 8
1789                                 ADD_CODE(&td, MINT_CONV_U4_I8);
1790 #endif
1791                                 break;
1792                         default:
1793                                 g_assert_not_reached ();
1794                         }
1795                         ++td.ip;
1796                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
1797                         break;
1798                 case CEE_CONV_I4:
1799                         CHECK_STACK (&td, 1);
1800                         switch (td.sp [-1].type) {
1801                         case STACK_TYPE_R8:
1802                                 ADD_CODE(&td, MINT_CONV_I4_R8);
1803                                 break;
1804                         case STACK_TYPE_I4:
1805                                 break;
1806                         case STACK_TYPE_I8:
1807                                 ADD_CODE(&td, MINT_CONV_I4_I8);
1808                                 break;
1809                         case STACK_TYPE_MP:
1810 #if SIZEOF_VOID_P == 8
1811                                 ADD_CODE(&td, MINT_CONV_I4_I8);
1812 #endif
1813                                 break;
1814                         default:
1815                                 g_assert_not_reached ();
1816                         }
1817                         ++td.ip;
1818                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
1819                         break;
1820                 case CEE_CONV_I8:
1821                         CHECK_STACK (&td, 1);
1822                         switch (td.sp [-1].type) {
1823                         case STACK_TYPE_R8:
1824                                 ADD_CODE(&td, MINT_CONV_I8_R8);
1825                                 break;
1826                         case STACK_TYPE_I4:
1827                                 ADD_CODE(&td, MINT_CONV_I8_I4);
1828                                 break;
1829                         case STACK_TYPE_I8:
1830                                 break;
1831                         case STACK_TYPE_MP:
1832 #if SIZEOF_VOID_P == 4
1833                                 ADD_CODE(&td, MINT_CONV_I8_I4);
1834 #endif
1835                                 break;
1836                         default:
1837                                 g_assert_not_reached ();
1838                         }
1839                         ++td.ip;
1840                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I8);
1841                         break;
1842                 case CEE_CONV_R4:
1843                         CHECK_STACK (&td, 1);
1844                         switch (td.sp [-1].type) {
1845                         case STACK_TYPE_R8:
1846                                 ADD_CODE(&td, MINT_CONV_R4_R8);
1847                                 break;
1848                         case STACK_TYPE_I8:
1849                                 ADD_CODE(&td, MINT_CONV_R4_I8);
1850                                 break;
1851                         case STACK_TYPE_I4:
1852                                 ADD_CODE(&td, MINT_CONV_R4_I4);
1853                                 break;
1854                         default:
1855                                 g_assert_not_reached ();
1856                         }
1857                         ++td.ip;
1858                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_R8);
1859                         break;
1860                 case CEE_CONV_R8:
1861                         CHECK_STACK (&td, 1);
1862                         switch (td.sp [-1].type) {
1863                         case STACK_TYPE_I4:
1864                                 ADD_CODE(&td, MINT_CONV_R8_I4);
1865                                 break;
1866                         case STACK_TYPE_I8:
1867                                 ADD_CODE(&td, MINT_CONV_R8_I8);
1868                                 break;
1869                         case STACK_TYPE_R8:
1870                                 break;
1871                         default:
1872                                 g_assert_not_reached ();
1873                         }
1874                         ++td.ip;
1875                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_R8);
1876                         break;
1877                 case CEE_CONV_U8:
1878                         CHECK_STACK (&td, 1);
1879                         switch (td.sp [-1].type) {
1880                         case STACK_TYPE_I4:
1881                                 ADD_CODE(&td, MINT_CONV_U8_I4);
1882                                 break;
1883                         case STACK_TYPE_I8:
1884                                 break;
1885                         case STACK_TYPE_R8:
1886                                 ADD_CODE(&td, MINT_CONV_U8_R8);
1887                                 break;
1888                         case STACK_TYPE_MP:
1889 #if SIZEOF_VOID_P == 4
1890                                 ADD_CODE(&td, MINT_CONV_U8_I4);
1891 #endif
1892                                 break;
1893                         default:
1894                                 g_assert_not_reached ();
1895                         }
1896                         ++td.ip;
1897                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I8);
1898                         break;
1899                 case CEE_CPOBJ: {
1900                         CHECK_STACK (&td, 2);
1901
1902                         token = read32 (td.ip + 1);
1903                         klass = mono_class_get_full (image, token, generic_context);
1904
1905                         if (klass->valuetype) {
1906                                 ADD_CODE (&td, MINT_CPOBJ);
1907                                 ADD_CODE (&td, get_data_item_index(&td, klass));
1908                         } else {
1909                                 ADD_CODE (&td, MINT_LDIND_REF);
1910                                 ADD_CODE (&td, MINT_STIND_REF);
1911                         }
1912                         td.ip += 5;
1913                         td.sp -= 2;
1914                         break;
1915                 }
1916                 case CEE_LDOBJ: {
1917                         int size;
1918                         CHECK_STACK (&td, 1);
1919
1920                         token = read32 (td.ip + 1);
1921
1922                         if (method->wrapper_type != MONO_WRAPPER_NONE)
1923                                 klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
1924                         else
1925                                 klass = mono_class_get_full (image, token, generic_context);
1926
1927                         ADD_CODE(&td, MINT_LDOBJ);
1928                         ADD_CODE(&td, get_data_item_index(&td, klass));
1929                         if (mint_type (&klass->byval_arg) == MINT_TYPE_VT) {
1930                                 size = mono_class_value_size (klass, NULL);
1931                                 PUSH_VT(&td, size);
1932                         }
1933                         td.ip += 5;
1934                         SET_TYPE(td.sp - 1, stack_type[mint_type(&klass->byval_arg)], klass);
1935                         break;
1936                 }
1937                 case CEE_LDSTR: {
1938                         MonoString *s;
1939                         token = mono_metadata_token_index (read32 (td.ip + 1));
1940                         td.ip += 5;
1941                         if (method->wrapper_type != MONO_WRAPPER_NONE) {
1942                                 s = mono_string_new_wrapper(
1943                                         mono_method_get_wrapper_data (method, token));
1944                         }
1945                         else
1946                                 s = mono_ldstr (domain, image, token);
1947                         ADD_CODE(&td, MINT_LDSTR);
1948                         ADD_CODE(&td, get_data_item_index (&td, s));
1949                         PUSH_TYPE(&td, STACK_TYPE_O, mono_defaults.string_class);
1950                         break;
1951                 }
1952                 case CEE_NEWOBJ: {
1953                         MonoMethod *m;
1954                         MonoMethodSignature *csignature;
1955                         guint32 vt_stack_used = 0;
1956                         guint32 vt_res_size = 0;
1957
1958                         td.ip++;
1959                         token = read32 (td.ip);
1960                         td.ip += 4;
1961
1962                         if (method->wrapper_type != MONO_WRAPPER_NONE)
1963                                 m = (MonoMethod *)mono_method_get_wrapper_data (method, token);
1964                         else 
1965                                 m = mono_get_method_full (image, token, NULL, generic_context);
1966
1967                         csignature = mono_method_signature (m);
1968                         klass = m->klass;
1969                         td.sp -= csignature->param_count;
1970                         ADD_CODE(&td, MINT_NEWOBJ);
1971                         ADD_CODE(&td, get_data_item_index (&td, mono_interp_get_runtime_method (domain, m, &error)));
1972                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
1973
1974                         if (mint_type (&klass->byval_arg) == MINT_TYPE_VT) {
1975                                 vt_res_size = mono_class_value_size (klass, NULL);
1976                                 PUSH_VT (&td, vt_res_size);
1977                         }
1978                         for (i = 0; i < csignature->param_count; ++i) {
1979                                 int mt = mint_type(csignature->params [i]);
1980                                 if (mt == MINT_TYPE_VT) {
1981                                         MonoClass *k = mono_class_from_mono_type (csignature->params [i]);
1982                                         gint32 size = mono_class_value_size (k, NULL);
1983                                         size = (size + 7) & ~7;
1984                                         vt_stack_used += size;
1985                                 }
1986                         }
1987                         if (vt_stack_used != 0 || vt_res_size != 0) {
1988                                 ADD_CODE(&td, MINT_VTRESULT);
1989                                 ADD_CODE(&td, vt_res_size);
1990                                 WRITE32(&td, &vt_stack_used);
1991                                 td.vt_sp -= vt_stack_used;
1992                         }
1993                         PUSH_TYPE (&td, stack_type [mint_type (&klass->byval_arg)], klass);
1994                         break;
1995                 }
1996                 case CEE_CASTCLASS:
1997                         CHECK_STACK (&td, 1);
1998                         token = read32 (td.ip + 1);
1999                         klass = mini_get_class (method, token, generic_context);
2000                         ADD_CODE(&td, MINT_CASTCLASS);
2001                         ADD_CODE(&td, get_data_item_index (&td, klass));
2002                         td.sp [-1].klass = klass;
2003                         td.ip += 5;
2004                         break;
2005                 case CEE_ISINST:
2006                         CHECK_STACK (&td, 1);
2007                         token = read32 (td.ip + 1);
2008                         klass = mini_get_class (method, token, generic_context);
2009                         ADD_CODE(&td, MINT_ISINST);
2010                         ADD_CODE(&td, get_data_item_index (&td, klass));
2011                         td.ip += 5;
2012                         break;
2013                 case CEE_CONV_R_UN:
2014                         switch (td.sp [-1].type) {
2015                         case STACK_TYPE_R8:
2016                                 break;
2017                         case STACK_TYPE_I8:
2018                                 ADD_CODE(&td, MINT_CONV_R_UN_I8);
2019                                 break;
2020                         case STACK_TYPE_I4:
2021                                 ADD_CODE(&td, MINT_CONV_R_UN_I4);
2022                                 break;
2023                         default:
2024                                 g_assert_not_reached ();
2025                         }
2026                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_R8);
2027                         ++td.ip;
2028                         break;
2029                 case CEE_UNBOX:
2030                         CHECK_STACK (&td, 1);
2031                         token = read32 (td.ip + 1);
2032                         
2033                         if (method->wrapper_type != MONO_WRAPPER_NONE)
2034                                 klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
2035                         else 
2036                                 klass = mono_class_get_full (image, token, generic_context);
2037
2038                         if (mono_class_is_nullable (klass)) {
2039                                 g_error ("cee_unbox: implement Nullable");
2040                         }
2041                         
2042                         ADD_CODE(&td, MINT_UNBOX);
2043                         ADD_CODE(&td, get_data_item_index (&td, klass));
2044                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_MP);
2045                         td.ip += 5;
2046                         break;
2047                 case CEE_UNBOX_ANY:
2048                         CHECK_STACK (&td, 1);
2049                         token = read32 (td.ip + 1);
2050
2051                         klass = mini_get_class (method, token, generic_context);
2052
2053                         if (mini_type_is_reference (&klass->byval_arg)) {
2054                                 int mt = mint_type (&klass->byval_arg);
2055                                 ADD_CODE (&td, MINT_CASTCLASS);
2056                                 ADD_CODE (&td, get_data_item_index (&td, klass));
2057                                 SET_TYPE (td.sp - 1, stack_type [mt], klass);
2058                                 td.ip += 5;
2059                         } else if (mono_class_is_nullable (klass)) {
2060                                 MonoMethod *target_method = mono_class_get_method_from_name (klass, "Unbox", 1);
2061                                 /* td.ip is incremented by interp_transform_call */
2062                                 interp_transform_call (&td, method, target_method, domain, generic_context, is_bb_start, body_start_offset, NULL, FALSE);
2063                         } else {
2064                                 int mt = mint_type (&klass->byval_arg);
2065                                 ADD_CODE (&td, MINT_UNBOX);
2066                                 ADD_CODE (&td, get_data_item_index (&td, klass));
2067
2068                                 ADD_CODE (&td, MINT_LDOBJ);
2069                                 ADD_CODE (&td, get_data_item_index(&td, klass));
2070                                 SET_TYPE (td.sp - 1, stack_type [mt], klass);
2071
2072                                 if (mt == MINT_TYPE_VT) {
2073                                         int size = mono_class_value_size (klass, NULL);
2074                                         PUSH_VT (&td, size);
2075                                 }
2076                                 td.ip += 5;
2077                         }
2078
2079                         break;
2080                 case CEE_THROW:
2081                         CHECK_STACK (&td, 1);
2082                         SIMPLE_OP (td, MINT_THROW);
2083                         --td.sp;
2084                         generating_code = 0;
2085                         break;
2086                 case CEE_LDFLDA:
2087                         CHECK_STACK (&td, 1);
2088                         token = read32 (td.ip + 1);
2089                         field = interp_field_from_token (method, token, &klass, generic_context);
2090                         gboolean is_static = !!(field->type->attrs & FIELD_ATTRIBUTE_STATIC);
2091                         mono_class_init (klass);
2092                         if (is_static) {
2093                                 ADD_CODE (&td, MINT_POP);
2094                                 ADD_CODE (&td, 0);
2095                                 ADD_CODE (&td, MINT_LDSFLDA);
2096                                 ADD_CODE (&td, get_data_item_index (&td, field));
2097                         } else {
2098                                 if ((td.sp - 1)->type == STACK_TYPE_O) {
2099                                         ADD_CODE (&td, MINT_LDFLDA);
2100                                 } else {
2101                                         g_assert ((td.sp -1)->type == STACK_TYPE_MP);
2102                                         ADD_CODE (&td, MINT_LDFLDA_UNSAFE);
2103                                 }
2104                                 ADD_CODE (&td, klass->valuetype ? field->offset - sizeof (MonoObject) : field->offset);
2105                         }
2106                         td.ip += 5;
2107                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_MP);
2108                         break;
2109                 case CEE_LDFLD: {
2110                         CHECK_STACK (&td, 1);
2111                         token = read32 (td.ip + 1);
2112                         field = interp_field_from_token (method, token, &klass, generic_context);
2113                         gboolean is_static = !!(field->type->attrs & FIELD_ATTRIBUTE_STATIC);
2114                         mono_class_init (klass);
2115
2116                         MonoClass *field_klass = mono_class_from_mono_type (field->type);
2117                         mt = mint_type (&field_klass->byval_arg);
2118                         if (klass->marshalbyref) {
2119                                 g_assert (!is_static);
2120                                 ADD_CODE(&td, mt == MINT_TYPE_VT ? MINT_LDRMFLD_VT :  MINT_LDRMFLD);
2121                                 ADD_CODE(&td, get_data_item_index (&td, field));
2122                         } else  {
2123                                 if (is_static) {
2124                                         ADD_CODE (&td, MINT_POP);
2125                                         ADD_CODE (&td, 0);
2126                                         ADD_CODE (&td, mt == MINT_TYPE_VT ? MINT_LDSFLD_VT : MINT_LDSFLD);
2127                                         ADD_CODE (&td, get_data_item_index (&td, field));
2128                                 } else {
2129                                         ADD_CODE (&td, MINT_LDFLD_I1 + mt - MINT_TYPE_I1);
2130                                         ADD_CODE (&td, klass->valuetype ? field->offset - sizeof(MonoObject) : field->offset);
2131                                 }
2132                         }
2133                         if (mt == MINT_TYPE_VT) {
2134                                 int size = mono_class_value_size (field_klass, NULL);
2135                                 PUSH_VT(&td, size);
2136                                 WRITE32(&td, &size);
2137                         }
2138                         if (td.sp [-1].type == STACK_TYPE_VT) {
2139                                 int size = mono_class_value_size (klass, NULL);
2140                                 size = (size + 7) & ~7;
2141                                 td.vt_sp -= size;
2142                                 ADD_CODE (&td, MINT_VTRESULT);
2143                                 ADD_CODE (&td, 0);
2144                                 WRITE32 (&td, &size);
2145                         }
2146                         td.ip += 5;
2147                         SET_TYPE(td.sp - 1, stack_type [mt], field_klass);
2148                         break;
2149                 }
2150                 case CEE_STFLD: {
2151                         CHECK_STACK (&td, 2);
2152                         token = read32 (td.ip + 1);
2153                         field = interp_field_from_token (method, token, &klass, generic_context);
2154                         gboolean is_static = !!(field->type->attrs & FIELD_ATTRIBUTE_STATIC);
2155                         mono_class_init (klass);
2156                         mt = mint_type(field->type);
2157
2158                         if (klass->marshalbyref) {
2159                                 g_assert (!is_static);
2160                                 ADD_CODE(&td, mt == MINT_TYPE_VT ? MINT_STRMFLD_VT : MINT_STRMFLD);
2161                                 ADD_CODE(&td, get_data_item_index (&td, field));
2162                         } else  {
2163                                 if (is_static) {
2164                                         ADD_CODE (&td, MINT_POP);
2165                                         ADD_CODE (&td, 1);
2166                                         ADD_CODE (&td, mt == MINT_TYPE_VT ? MINT_STSFLD_VT : MINT_STSFLD);
2167                                         ADD_CODE (&td, get_data_item_index (&td, field));
2168                                 } else {
2169                                         ADD_CODE (&td, MINT_STFLD_I1 + mt - MINT_TYPE_I1);
2170                                         ADD_CODE (&td, klass->valuetype ? field->offset - sizeof(MonoObject) : field->offset);
2171                                 }
2172                         }
2173                         if (mt == MINT_TYPE_VT) {
2174                                 MonoClass *klass = mono_class_from_mono_type (field->type);
2175                                 int size = mono_class_value_size (klass, NULL);
2176                                 POP_VT(&td, size);
2177                                 WRITE32(&td, &size);
2178                         }
2179                         td.ip += 5;
2180                         td.sp -= 2;
2181                         break;
2182                 }
2183                 case CEE_LDSFLDA:
2184                         token = read32 (td.ip + 1);
2185                         field = interp_field_from_token (method, token, &klass, generic_context);
2186                         ADD_CODE(&td, MINT_LDSFLDA);
2187                         ADD_CODE(&td, get_data_item_index (&td, field));
2188                         td.ip += 5;
2189                         PUSH_SIMPLE_TYPE(&td, STACK_TYPE_MP);
2190                         break;
2191                 case CEE_LDSFLD:
2192                         token = read32 (td.ip + 1);
2193                         field = interp_field_from_token (method, token, &klass, generic_context);
2194                         mt = mint_type(field->type);
2195                         ADD_CODE(&td, mt == MINT_TYPE_VT ? MINT_LDSFLD_VT : MINT_LDSFLD);
2196                         ADD_CODE(&td, get_data_item_index (&td, field));
2197                         klass = NULL;
2198                         if (mt == MINT_TYPE_VT) {
2199                                 MonoClass *klass = mono_class_from_mono_type (field->type);
2200                                 int size = mono_class_value_size (klass, NULL);
2201                                 PUSH_VT(&td, size);
2202                                 WRITE32(&td, &size);
2203                                 klass = field->type->data.klass;
2204                         } else {
2205                                 if (mt == MINT_TYPE_O) 
2206                                         klass = mono_class_from_mono_type (field->type);
2207                         }
2208                         td.ip += 5;
2209                         PUSH_TYPE(&td, stack_type [mt], klass);
2210                         break;
2211                 case CEE_STSFLD:
2212                         CHECK_STACK (&td, 1);
2213                         token = read32 (td.ip + 1);
2214                         field = interp_field_from_token (method, token, &klass, generic_context);
2215                         mt = mint_type(field->type);
2216                         ADD_CODE(&td, mt == MINT_TYPE_VT ? MINT_STSFLD_VT : MINT_STSFLD);
2217                         ADD_CODE(&td, get_data_item_index (&td, field));
2218                         if (mt == MINT_TYPE_VT) {
2219                                 MonoClass *klass = mono_class_from_mono_type (field->type);
2220                                 int size = mono_class_value_size (klass, NULL);
2221                                 POP_VT (&td, size);
2222                                 WRITE32 (&td, &size);
2223                         }
2224                         td.ip += 5;
2225                         --td.sp;
2226                         break;
2227                 case CEE_STOBJ: {
2228                         int size;
2229                         token = read32 (td.ip + 1);
2230
2231                         if (method->wrapper_type != MONO_WRAPPER_NONE)
2232                                 klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
2233                         else
2234                                 klass = mini_get_class (method, token, generic_context);
2235
2236                         ADD_CODE(&td, td.sp [-1].type == STACK_TYPE_VT ? MINT_STOBJ_VT : MINT_STOBJ);
2237                         ADD_CODE(&td, get_data_item_index (&td, klass));
2238                         if (td.sp [-1].type == STACK_TYPE_VT) {
2239                                 size = mono_class_value_size (klass, NULL);
2240                                 size = (size + 7) & ~7;
2241                                 td.vt_sp -= size;
2242                         }
2243                         td.ip += 5;
2244                         td.sp -= 2;
2245                         break;
2246                 }
2247                 case CEE_CONV_OVF_I_UN:
2248                 case CEE_CONV_OVF_U_UN:
2249                         CHECK_STACK (&td, 1);
2250                         switch (td.sp [-1].type) {
2251                         case STACK_TYPE_R8:
2252 #if SIZEOF_VOID_P == 8
2253                                 ADD_CODE(&td, MINT_CONV_OVF_I8_UN_R8);
2254 #else
2255                                 ADD_CODE(&td, MINT_CONV_OVF_I4_UN_R8);
2256 #endif
2257                                 break;
2258                         case STACK_TYPE_I8:
2259 #if SIZEOF_VOID_P == 4
2260                                 ADD_CODE (&td, MINT_CONV_OVF_I4_UN_I8);
2261 #endif
2262                                 break;
2263                         case STACK_TYPE_I4:
2264 #if SIZEOF_VOID_P == 8
2265                                 ADD_CODE(&td, MINT_CONV_I8_U4);
2266 #endif
2267                                 break;
2268                         default:
2269                                 g_assert_not_reached ();
2270                                 break;
2271                         }
2272                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I8);
2273                         ++td.ip;
2274                         break;
2275                 case CEE_CONV_OVF_I8_UN:
2276                 case CEE_CONV_OVF_U8_UN:
2277                         CHECK_STACK (&td, 1);
2278                         switch (td.sp [-1].type) {
2279                         case STACK_TYPE_R8:
2280                                 ADD_CODE(&td, MINT_CONV_OVF_I8_UN_R8);
2281                                 break;
2282                         case STACK_TYPE_I8:
2283                                 if (*td.ip == CEE_CONV_OVF_I8_UN)
2284                                         ADD_CODE (&td, MINT_CONV_OVF_I8_U8);
2285                                 break;
2286                         case STACK_TYPE_I4:
2287                                 ADD_CODE(&td, MINT_CONV_I8_U4);
2288                                 break;
2289                         default:
2290                                 g_assert_not_reached ();
2291                                 break;
2292                         }
2293                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I8);
2294                         ++td.ip;
2295                         break;
2296                 case CEE_BOX: {
2297                         int size;
2298                         CHECK_STACK (&td, 1);
2299                         token = read32 (td.ip + 1);
2300                         if (method->wrapper_type != MONO_WRAPPER_NONE)
2301                                 klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
2302                         else
2303                                 klass = mini_get_class (method, token, generic_context);
2304
2305                         if (mono_class_is_nullable (klass)) {
2306                                 MonoMethod *target_method = mono_class_get_method_from_name (klass, "Box", 1);
2307                                 /* td.ip is incremented by interp_transform_call */
2308                                 interp_transform_call (&td, method, target_method, domain, generic_context, is_bb_start, body_start_offset, NULL, FALSE);
2309                         } else if (!klass->valuetype) {
2310                                 /* already boxed, do nothing. */
2311                                 td.ip += 5;
2312                         } else {
2313                                 if (mint_type (&klass->byval_arg) == MINT_TYPE_VT && !klass->enumtype) {
2314                                         size = mono_class_value_size (klass, NULL);
2315                                         size = (size + 7) & ~7;
2316                                         td.vt_sp -= size;
2317                                 }
2318                                 ADD_CODE(&td, MINT_BOX);
2319                                 ADD_CODE(&td, get_data_item_index (&td, klass));
2320                                 ADD_CODE (&td, 0);
2321                                 SET_TYPE(td.sp - 1, STACK_TYPE_O, klass);
2322                                 td.ip += 5;
2323                         }
2324
2325                         break;
2326                 }
2327                 case CEE_NEWARR: {
2328                         CHECK_STACK (&td, 1);
2329                         token = read32 (td.ip + 1);
2330
2331                         if (method->wrapper_type != MONO_WRAPPER_NONE)
2332                                 klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
2333                         else
2334                                 klass = mini_get_class (method, token, generic_context);
2335
2336                         unsigned char lentype = (td.sp - 1)->type;
2337                         if (lentype == STACK_TYPE_I8) {
2338                                 /* mimic mini behaviour */
2339                                 ADD_CODE (&td, MINT_CONV_OVF_U4_I8);
2340                         } else {
2341                                 g_assert (lentype == STACK_TYPE_I4);
2342                                 ADD_CODE (&td, MINT_CONV_OVF_U4_I4);
2343                         }
2344                         SET_SIMPLE_TYPE (td.sp - 1, STACK_TYPE_I4);
2345                         ADD_CODE (&td, MINT_NEWARR);
2346                         ADD_CODE (&td, get_data_item_index (&td, klass));
2347                         SET_TYPE (td.sp - 1, STACK_TYPE_O, klass);
2348                         td.ip += 5;
2349                         break;
2350                 }
2351                 case CEE_LDLEN:
2352                         CHECK_STACK (&td, 1);
2353                         SIMPLE_OP (td, MINT_LDLEN);
2354                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I);
2355                         break;
2356                 case CEE_LDELEMA:
2357                         CHECK_STACK (&td, 2);
2358                         ENSURE_I4 (&td, 1);
2359                         token = read32 (td.ip + 1);
2360
2361                         if (method->wrapper_type != MONO_WRAPPER_NONE)
2362                                 klass = (MonoClass *) mono_method_get_wrapper_data (method, token);
2363                         else
2364                                 klass = mini_get_class (method, token, generic_context);
2365
2366                         if (!klass->valuetype && method->wrapper_type == MONO_WRAPPER_NONE && !readonly) {
2367                                 ADD_CODE (&td, MINT_LDELEMA_TC);
2368                         } else {
2369                                 ADD_CODE (&td, MINT_LDELEMA);
2370                         }
2371                         ADD_CODE (&td, get_data_item_index (&td, klass));
2372                         /* according to spec, ldelema bytecode is only used for 1-dim arrays */
2373                         ADD_CODE (&td, 2);
2374                         readonly = FALSE;
2375
2376                         td.ip += 5;
2377                         --td.sp;
2378                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_MP);
2379                         break;
2380                 case CEE_LDELEM_I1:
2381                         CHECK_STACK (&td, 2);
2382                         ENSURE_I4 (&td, 1);
2383                         SIMPLE_OP (td, MINT_LDELEM_I1);
2384                         --td.sp;
2385                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
2386                         break;
2387                 case CEE_LDELEM_U1:
2388                         CHECK_STACK (&td, 2);
2389                         ENSURE_I4 (&td, 1);
2390                         SIMPLE_OP (td, MINT_LDELEM_U1);
2391                         --td.sp;
2392                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
2393                         break;
2394                 case CEE_LDELEM_I2:
2395                         CHECK_STACK (&td, 2);
2396                         ENSURE_I4 (&td, 1);
2397                         SIMPLE_OP (td, MINT_LDELEM_I2);
2398                         --td.sp;
2399                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
2400                         break;
2401                 case CEE_LDELEM_U2:
2402                         CHECK_STACK (&td, 2);
2403                         ENSURE_I4 (&td, 1);
2404                         SIMPLE_OP (td, MINT_LDELEM_U2);
2405                         --td.sp;
2406                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
2407                         break;
2408                 case CEE_LDELEM_I4:
2409                         CHECK_STACK (&td, 2);
2410                         ENSURE_I4 (&td, 1);
2411                         SIMPLE_OP (td, MINT_LDELEM_I4);
2412                         --td.sp;
2413                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
2414                         break;
2415                 case CEE_LDELEM_U4:
2416                         CHECK_STACK (&td, 2);
2417                         ENSURE_I4 (&td, 1);
2418                         SIMPLE_OP (td, MINT_LDELEM_U4);
2419                         --td.sp;
2420                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
2421                         break;
2422                 case CEE_LDELEM_I8:
2423                         CHECK_STACK (&td, 2);
2424                         ENSURE_I4 (&td, 1);
2425                         SIMPLE_OP (td, MINT_LDELEM_I8);
2426                         --td.sp;
2427                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I8);
2428                         break;
2429                 case CEE_LDELEM_I:
2430                         CHECK_STACK (&td, 2);
2431                         ENSURE_I4 (&td, 1);
2432                         SIMPLE_OP (td, MINT_LDELEM_I);
2433                         --td.sp;
2434                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I);
2435                         break;
2436                 case CEE_LDELEM_R4:
2437                         CHECK_STACK (&td, 2);
2438                         ENSURE_I4 (&td, 1);
2439                         SIMPLE_OP (td, MINT_LDELEM_R4);
2440                         --td.sp;
2441                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_R8);
2442                         break;
2443                 case CEE_LDELEM_R8:
2444                         CHECK_STACK (&td, 2);
2445                         ENSURE_I4 (&td, 1);
2446                         SIMPLE_OP (td, MINT_LDELEM_R8);
2447                         --td.sp;
2448                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_R8);
2449                         break;
2450                 case CEE_LDELEM_REF:
2451                         CHECK_STACK (&td, 2);
2452                         ENSURE_I4 (&td, 1);
2453                         SIMPLE_OP (td, MINT_LDELEM_REF);
2454                         --td.sp;
2455                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_O);
2456                         break;
2457                 case CEE_LDELEM:
2458                         CHECK_STACK (&td, 2);
2459                         token = read32 (td.ip + 1);
2460                         klass = mini_get_class (method, token, generic_context);
2461                         switch (mint_type (&klass->byval_arg)) {
2462                                 case MINT_TYPE_I1:
2463                                         ENSURE_I4 (&td, 1);
2464                                         SIMPLE_OP (td, MINT_LDELEM_I1);
2465                                         --td.sp;
2466                                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
2467                                         break;
2468                                 case MINT_TYPE_U1:
2469                                         ENSURE_I4 (&td, 1);
2470                                         SIMPLE_OP (td, MINT_LDELEM_U1);
2471                                         --td.sp;
2472                                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
2473                                         break;
2474                                 case MINT_TYPE_U2:
2475                                         ENSURE_I4 (&td, 1);
2476                                         SIMPLE_OP (td, MINT_LDELEM_U2);
2477                                         --td.sp;
2478                                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
2479                                         break;
2480                                 case MINT_TYPE_I2:
2481                                         ENSURE_I4 (&td, 1);
2482                                         SIMPLE_OP (td, MINT_LDELEM_I2);
2483                                         --td.sp;
2484                                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
2485                                         break;
2486                                 case MINT_TYPE_I4:
2487                                         ENSURE_I4 (&td, 1);
2488                                         SIMPLE_OP (td, MINT_LDELEM_I4);
2489                                         --td.sp;
2490                                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
2491                                         break;
2492                                 case MINT_TYPE_I8:
2493                                         ENSURE_I4 (&td, 1);
2494                                         SIMPLE_OP (td, MINT_LDELEM_I8);
2495                                         --td.sp;
2496                                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I8);
2497                                         break;
2498                                 case MINT_TYPE_R4:
2499                                         ENSURE_I4 (&td, 1);
2500                                         SIMPLE_OP (td, MINT_LDELEM_R4);
2501                                         --td.sp;
2502                                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_R8);
2503                                         break;
2504                                 case MINT_TYPE_R8:
2505                                         ENSURE_I4 (&td, 1);
2506                                         SIMPLE_OP (td, MINT_LDELEM_R8);
2507                                         --td.sp;
2508                                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_R8);
2509                                         break;
2510                                 case MINT_TYPE_O:
2511                                         ENSURE_I4 (&td, 1);
2512                                         SIMPLE_OP (td, MINT_LDELEM_REF);
2513                                         --td.sp;
2514                                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_O);
2515                                         break;
2516                                 case MINT_TYPE_VT: {
2517                                         int size = mono_class_value_size (klass, NULL);
2518                                         ENSURE_I4 (&td, 1);
2519                                         SIMPLE_OP (td, MINT_LDELEM_VT);
2520                                         ADD_CODE (&td, get_data_item_index (&td, klass));
2521                                         WRITE32 (&td, &size);
2522                                         --td.sp;
2523                                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_VT);
2524                                         PUSH_VT (&td, size);
2525                                         break;
2526                                 }
2527                                 default: {
2528                                         GString *res = g_string_new ("");
2529                                         mono_type_get_desc (res, &klass->byval_arg, TRUE);
2530                                         g_print ("LDELEM: %s -> %d (%s)\n", klass->name, mint_type (&klass->byval_arg), res->str);
2531                                         g_string_free (res, TRUE);
2532                                         g_assert (0);
2533                                         break;
2534                                 }
2535                         }
2536                         td.ip += 4;
2537                         break;
2538                 case CEE_STELEM_I:
2539                         CHECK_STACK (&td, 3);
2540                         ENSURE_I4 (&td, 2);
2541                         SIMPLE_OP (td, MINT_STELEM_I);
2542                         td.sp -= 3;
2543                         break;
2544                 case CEE_STELEM_I1:
2545                         CHECK_STACK (&td, 3);
2546                         ENSURE_I4 (&td, 2);
2547                         SIMPLE_OP (td, MINT_STELEM_I1);
2548                         td.sp -= 3;
2549                         break;
2550                 case CEE_STELEM_I2:
2551                         CHECK_STACK (&td, 3);
2552                         ENSURE_I4 (&td, 2);
2553                         SIMPLE_OP (td, MINT_STELEM_I2);
2554                         td.sp -= 3;
2555                         break;
2556                 case CEE_STELEM_I4:
2557                         CHECK_STACK (&td, 3);
2558                         ENSURE_I4 (&td, 2);
2559                         SIMPLE_OP (td, MINT_STELEM_I4);
2560                         td.sp -= 3;
2561                         break;
2562                 case CEE_STELEM_I8:
2563                         CHECK_STACK (&td, 3);
2564                         ENSURE_I4 (&td, 2);
2565                         SIMPLE_OP (td, MINT_STELEM_I8);
2566                         td.sp -= 3;
2567                         break;
2568                 case CEE_STELEM_R4:
2569                         CHECK_STACK (&td, 3);
2570                         ENSURE_I4 (&td, 2);
2571                         SIMPLE_OP (td, MINT_STELEM_R4);
2572                         td.sp -= 3;
2573                         break;
2574                 case CEE_STELEM_R8:
2575                         CHECK_STACK (&td, 3);
2576                         ENSURE_I4 (&td, 2);
2577                         SIMPLE_OP (td, MINT_STELEM_R8);
2578                         td.sp -= 3;
2579                         break;
2580                 case CEE_STELEM_REF:
2581                         CHECK_STACK (&td, 3);
2582                         ENSURE_I4 (&td, 2);
2583                         SIMPLE_OP (td, MINT_STELEM_REF);
2584                         td.sp -= 3;
2585                         break;
2586                 case CEE_STELEM:
2587                         CHECK_STACK (&td, 3);
2588                         ENSURE_I4 (&td, 2);
2589                         token = read32 (td.ip + 1);
2590                         klass = mini_get_class (method, token, generic_context);
2591                         switch (mint_type (&klass->byval_arg)) {
2592                                 case MINT_TYPE_U1:
2593                                         SIMPLE_OP (td, MINT_STELEM_U1);
2594                                         break;
2595                                 case MINT_TYPE_U2:
2596                                         SIMPLE_OP (td, MINT_STELEM_U2);
2597                                         break;
2598                                 case MINT_TYPE_I4:
2599                                         SIMPLE_OP (td, MINT_STELEM_I4);
2600                                         break;
2601                                 case MINT_TYPE_I8:
2602                                         SIMPLE_OP (td, MINT_STELEM_I8);
2603                                         break;
2604                                 case MINT_TYPE_O:
2605                                         SIMPLE_OP (td, MINT_STELEM_REF);
2606                                         break;
2607                                 case MINT_TYPE_VT: {
2608                                         int size = mono_class_value_size (klass, NULL);
2609                                         SIMPLE_OP (td, MINT_STELEM_VT);
2610                                         ADD_CODE (&td, get_data_item_index (&td, klass));
2611                                         WRITE32 (&td, &size);
2612                                         POP_VT (&td, size);
2613                                         break;
2614                                 }
2615                                 default: {
2616                                         GString *res = g_string_new ("");
2617                                         mono_type_get_desc (res, &klass->byval_arg, TRUE);
2618                                         g_print ("STELEM: %s -> %d (%s)\n", klass->name, mint_type (&klass->byval_arg), res->str);
2619                                         g_string_free (res, TRUE);
2620                                         g_assert (0);
2621                                         break;
2622                                 }
2623                         }
2624                         td.ip += 4;
2625                         td.sp -= 3;
2626                         break;
2627 #if 0
2628                 case CEE_CONV_OVF_U1:
2629
2630                 case CEE_CONV_OVF_I8:
2631
2632 #if SIZEOF_VOID_P == 8
2633                 case CEE_CONV_OVF_U:
2634 #endif
2635                 case CEE_REFANYVAL: ves_abort(); break;
2636 #endif
2637                 case CEE_CKFINITE:
2638                         CHECK_STACK (&td, 1);
2639                         SIMPLE_OP (td, MINT_CKFINITE);
2640                         break;
2641                 case CEE_CONV_OVF_I1:
2642                 case CEE_CONV_OVF_I1_UN:
2643                         CHECK_STACK (&td, 1);
2644                         switch (td.sp [-1].type) {
2645                         case STACK_TYPE_R8:
2646                                 ADD_CODE(&td, MINT_CONV_OVF_I1_R8);
2647                                 break;
2648                         case STACK_TYPE_I4:
2649                                 ADD_CODE(&td, MINT_CONV_OVF_I1_I4);
2650                                 break;
2651                         case STACK_TYPE_I8:
2652                                 ADD_CODE(&td, MINT_CONV_OVF_I1_I8);
2653                                 break;
2654                         default:
2655                                 g_assert_not_reached ();
2656                         }
2657                         ++td.ip;
2658                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
2659                         break;
2660                 case CEE_CONV_OVF_U1:
2661                 case CEE_CONV_OVF_U1_UN:
2662                         CHECK_STACK (&td, 1);
2663                         switch (td.sp [-1].type) {
2664                         case STACK_TYPE_R8:
2665                                 ADD_CODE(&td, MINT_CONV_OVF_U1_R8);
2666                                 break;
2667                         case STACK_TYPE_I4:
2668                                 ADD_CODE(&td, MINT_CONV_OVF_U1_I4);
2669                                 break;
2670                         case STACK_TYPE_I8:
2671                                 ADD_CODE(&td, MINT_CONV_OVF_U1_I8);
2672                                 break;
2673                         default:
2674                                 g_assert_not_reached ();
2675                         }
2676                         ++td.ip;
2677                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
2678                         break;
2679                 case CEE_CONV_OVF_I2:
2680                 case CEE_CONV_OVF_I2_UN:
2681                         CHECK_STACK (&td, 1);
2682                         switch (td.sp [-1].type) {
2683                         case STACK_TYPE_R8:
2684                                 ADD_CODE(&td, MINT_CONV_OVF_I2_R8);
2685                                 break;
2686                         case STACK_TYPE_I4:
2687                                 ADD_CODE(&td, MINT_CONV_OVF_I2_I4);
2688                                 break;
2689                         case STACK_TYPE_I8:
2690                                 ADD_CODE(&td, MINT_CONV_OVF_I2_I8);
2691                                 break;
2692                         default:
2693                                 g_assert_not_reached ();
2694                         }
2695                         ++td.ip;
2696                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
2697                         break;
2698                 case CEE_CONV_OVF_U2_UN:
2699                 case CEE_CONV_OVF_U2:
2700                         CHECK_STACK (&td, 1);
2701                         switch (td.sp [-1].type) {
2702                         case STACK_TYPE_R8:
2703                                 ADD_CODE(&td, MINT_CONV_OVF_U2_R8);
2704                                 break;
2705                         case STACK_TYPE_I4:
2706                                 ADD_CODE(&td, MINT_CONV_OVF_U2_I4);
2707                                 break;
2708                         case STACK_TYPE_I8:
2709                                 ADD_CODE(&td, MINT_CONV_OVF_U2_I8);
2710                                 break;
2711                         default:
2712                                 g_assert_not_reached ();
2713                         }
2714                         ++td.ip;
2715                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
2716                         break;
2717 #if SIZEOF_VOID_P == 4
2718                 case CEE_CONV_OVF_I:
2719 #endif
2720                 case CEE_CONV_OVF_I4:
2721                 case CEE_CONV_OVF_I4_UN:
2722                         CHECK_STACK (&td, 1);
2723                         switch (td.sp [-1].type) {
2724                         case STACK_TYPE_R8:
2725                                 ADD_CODE(&td, MINT_CONV_OVF_I4_R8);
2726                                 break;
2727                         case STACK_TYPE_I4:
2728                                 if (*td.ip == CEE_CONV_OVF_I4_UN)
2729                                         ADD_CODE(&td, MINT_CONV_OVF_I4_U4);
2730                                 break;
2731                         case STACK_TYPE_I8:
2732                                 if (*td.ip == CEE_CONV_OVF_I4_UN)
2733                                         ADD_CODE (&td, MINT_CONV_OVF_I4_U8);
2734                                 else
2735                                         ADD_CODE (&td, MINT_CONV_OVF_I4_I8);
2736                                 break;
2737                         default:
2738                                 g_assert_not_reached ();
2739                         }
2740                         ++td.ip;
2741                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
2742                         break;
2743 #if SIZEOF_VOID_P == 4
2744                 case CEE_CONV_OVF_U:
2745 #endif
2746                 case CEE_CONV_OVF_U4:
2747                 case CEE_CONV_OVF_U4_UN:
2748                         CHECK_STACK (&td, 1);
2749                         switch (td.sp [-1].type) {
2750                         case STACK_TYPE_R8:
2751                                 ADD_CODE(&td, MINT_CONV_OVF_U4_R8);
2752                                 break;
2753                         case STACK_TYPE_I4:
2754                                 if (*td.ip != CEE_CONV_OVF_U4_UN)
2755                                         ADD_CODE(&td, MINT_CONV_OVF_U4_I4);
2756                                 break;
2757                         case STACK_TYPE_I8:
2758                                 ADD_CODE(&td, MINT_CONV_OVF_U4_I8);
2759                                 break;
2760                         default:
2761                                 g_assert_not_reached ();
2762                         }
2763                         ++td.ip;
2764                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
2765                         break;
2766 #if SIZEOF_VOID_P == 8
2767                 case CEE_CONV_OVF_I:
2768 #endif
2769                 case CEE_CONV_OVF_I8:
2770                         CHECK_STACK (&td, 1);
2771                         switch (td.sp [-1].type) {
2772                         case STACK_TYPE_R8:
2773                                 ADD_CODE(&td, MINT_CONV_OVF_I8_R8);
2774                                 break;
2775                         case STACK_TYPE_I4:
2776                                 ADD_CODE(&td, MINT_CONV_I8_I4);
2777                                 break;
2778                         case STACK_TYPE_I8:
2779                                 break;
2780                         default:
2781                                 g_assert_not_reached ();
2782                         }
2783                         ++td.ip;
2784                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I8);
2785                         break;
2786 #if SIZEOF_VOID_P == 8
2787                 case CEE_CONV_OVF_U:
2788 #endif
2789                 case CEE_CONV_OVF_U8:
2790                         CHECK_STACK (&td, 1);
2791                         switch (td.sp [-1].type) {
2792                         case STACK_TYPE_R8:
2793                                 ADD_CODE(&td, MINT_CONV_OVF_U8_R8);
2794                                 break;
2795                         case STACK_TYPE_I4:
2796                                 ADD_CODE(&td, MINT_CONV_OVF_U8_I4);
2797                                 break;
2798                         case STACK_TYPE_I8:
2799                                 ADD_CODE (&td, MINT_CONV_OVF_U8_I8);
2800                                 break;
2801                         default:
2802                                 g_assert_not_reached ();
2803                         }
2804                         ++td.ip;
2805                         SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I8);
2806                         break;
2807                 case CEE_LDTOKEN: {
2808                         int size;
2809                         gpointer handle;
2810                         token = read32 (td.ip + 1);
2811                         if (method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD || method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED) {
2812                                 handle = mono_method_get_wrapper_data (method, token);
2813                                 klass = (MonoClass *) mono_method_get_wrapper_data (method, token + 1);
2814                                 if (klass == mono_defaults.typehandle_class)
2815                                         handle = &((MonoClass *) handle)->byval_arg;
2816
2817                                 if (generic_context) {
2818                                         handle = mono_class_inflate_generic_type_checked (handle, generic_context, &error);
2819                                         mono_error_cleanup (&error); /* FIXME: don't swallow the error */
2820                                 }
2821                         } else {
2822                                 handle = mono_ldtoken (image, token, &klass, generic_context);
2823                         }
2824                         mono_class_init (klass);
2825                         mt = mint_type (&klass->byval_arg);
2826                         g_assert (mt == MINT_TYPE_VT);
2827                         size = mono_class_value_size (klass, NULL);
2828                         g_assert (size == sizeof(gpointer));
2829                         PUSH_VT (&td, sizeof(gpointer));
2830                         ADD_CODE (&td, MINT_LDTOKEN);
2831                         ADD_CODE (&td, get_data_item_index (&td, handle));
2832
2833                         SET_TYPE (td.sp, stack_type [mt], klass);
2834                         td.sp++;
2835                         td.ip += 5;
2836                         break;
2837                 }
2838                 case CEE_ADD_OVF:
2839                         binary_arith_op(&td, MINT_ADD_OVF_I4);
2840                         ++td.ip;
2841                         break;
2842                 case CEE_ADD_OVF_UN:
2843                         binary_arith_op(&td, MINT_ADD_OVF_UN_I4);
2844                         ++td.ip;
2845                         break;
2846                 case CEE_MUL_OVF:
2847                         binary_arith_op(&td, MINT_MUL_OVF_I4);
2848                         ++td.ip;
2849                         break;
2850                 case CEE_MUL_OVF_UN:
2851                         binary_arith_op(&td, MINT_MUL_OVF_UN_I4);
2852                         ++td.ip;
2853                         break;
2854                 case CEE_SUB_OVF:
2855                         binary_arith_op(&td, MINT_SUB_OVF_I4);
2856                         ++td.ip;
2857                         break;
2858                 case CEE_SUB_OVF_UN:
2859                         binary_arith_op(&td, MINT_SUB_OVF_UN_I4);
2860                         ++td.ip;
2861                         break;
2862                 case CEE_ENDFINALLY:
2863                         g_assert (td.clause_indexes [in_offset] != -1);
2864                         td.sp = td.stack;
2865                         SIMPLE_OP (td, MINT_ENDFINALLY);
2866                         ADD_CODE (&td, td.clause_indexes [in_offset]);
2867                         generating_code = 0;
2868                         break;
2869                 case CEE_LEAVE:
2870                         td.sp = td.stack;
2871                         handle_branch (&td, MINT_LEAVE_S, MINT_LEAVE, 5 + read32 (td.ip + 1));
2872                         td.ip += 5;
2873                         generating_code = 0;
2874                         break;
2875                 case CEE_LEAVE_S:
2876                         td.sp = td.stack;
2877                         handle_branch (&td, MINT_LEAVE_S, MINT_LEAVE, 2 + (gint8)td.ip [1]);
2878                         td.ip += 2;
2879                         generating_code = 0;
2880                         break;
2881                 case CEE_UNUSED41:
2882                         ++td.ip;
2883                         switch (*td.ip) {
2884                                 case CEE_MONO_CALLI_EXTRA_ARG:
2885                                         /* Same as CEE_CALLI, except that we drop the extra arg required for llvm specific behaviour */
2886                                         ADD_CODE (&td, MINT_POP);
2887                                         ADD_CODE (&td, 1);
2888                                         --td.sp;
2889                                         interp_transform_call (&td, method, NULL, domain, generic_context, is_bb_start, body_start_offset, NULL, FALSE);
2890                                         break;
2891                                 case CEE_MONO_JIT_ICALL_ADDR: {
2892                                         guint32 token;
2893                                         gpointer func;
2894                                         MonoJitICallInfo *info;
2895
2896                                         token = read32 (td.ip + 1);
2897                                         td.ip += 5;
2898                                         func = mono_method_get_wrapper_data (method, token);
2899                                         info = mono_find_jit_icall_by_addr (func);
2900
2901                                         ADD_CODE (&td, MINT_LDFTN);
2902                                         ADD_CODE (&td, get_data_item_index (&td, func));
2903                                         PUSH_SIMPLE_TYPE (&td, STACK_TYPE_I);
2904                                         break;
2905                                 }
2906                                 case CEE_MONO_ICALL: {
2907                                         guint32 token;
2908                                         gpointer func;
2909                                         MonoJitICallInfo *info;
2910
2911                                         token = read32 (td.ip + 1);
2912                                         td.ip += 5;
2913                                         func = mono_method_get_wrapper_data (method, token);
2914                                         info = mono_find_jit_icall_by_addr (func);
2915                                         g_assert (info);
2916
2917                                         CHECK_STACK (&td, info->sig->param_count);
2918                                         switch (info->sig->param_count) {
2919                                         case 0:
2920                                                 if (MONO_TYPE_IS_VOID (info->sig->ret))
2921                                                         ADD_CODE (&td,MINT_ICALL_V_V);
2922                                                 else
2923                                                         ADD_CODE (&td, MINT_ICALL_V_P);
2924                                                 break;
2925                                         case 1:
2926                                                 if (MONO_TYPE_IS_VOID (info->sig->ret))
2927                                                         ADD_CODE (&td,MINT_ICALL_P_V);
2928                                                 else
2929                                                         ADD_CODE (&td,MINT_ICALL_P_P);
2930                                                 break;
2931                                         case 2:
2932                                                 if (MONO_TYPE_IS_VOID (info->sig->ret)) {
2933                                                         if (info->sig->params [1]->type == MONO_TYPE_I4)
2934                                                                 ADD_CODE (&td,MINT_ICALL_PI_V);
2935                                                         else
2936                                                                 ADD_CODE (&td,MINT_ICALL_PP_V);
2937                                                 } else {
2938                                                         if (info->sig->params [1]->type == MONO_TYPE_I4)
2939                                                                 ADD_CODE (&td,MINT_ICALL_PI_P);
2940                                                         else
2941                                                                 ADD_CODE (&td,MINT_ICALL_PP_P);
2942                                                 }
2943                                                 break;
2944                                         case 3:
2945                                                 g_assert (MONO_TYPE_IS_VOID (info->sig->ret));
2946                                                 if (info->sig->params [2]->type == MONO_TYPE_I4)
2947                                                         ADD_CODE (&td,MINT_ICALL_PPI_V);
2948                                                 else
2949                                                         ADD_CODE (&td,MINT_ICALL_PPP_V);
2950                                                 break;
2951                                         default:
2952                                                 g_assert_not_reached ();
2953                                         }
2954
2955                                         if (func == mono_ftnptr_to_delegate) {
2956                                                 g_error ("TODO: ?");
2957                                         }
2958                                         ADD_CODE(&td, get_data_item_index (&td, func));
2959                                         td.sp -= info->sig->param_count;
2960
2961                                         if (!MONO_TYPE_IS_VOID (info->sig->ret)) {
2962                                                 td.sp ++;
2963                                                 SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I);
2964                                         }
2965                                         break;
2966                                 }
2967                         case CEE_MONO_VTADDR: {
2968                                 int size;
2969                                 CHECK_STACK (&td, 1);
2970                                 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
2971                                         size = mono_class_native_size(td.sp [-1].klass, NULL);
2972                                 else
2973                                         size = mono_class_value_size(td.sp [-1].klass, NULL);
2974                                 size = (size + 7) & ~7;
2975                                 ADD_CODE(&td, MINT_VTRESULT);
2976                                 ADD_CODE(&td, 0);
2977                                 WRITE32(&td, &size);
2978                                 td.vt_sp -= size;
2979                                 ++td.ip;
2980                                 SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_MP);
2981                                 break;
2982                         }
2983                         case CEE_MONO_LDPTR:
2984                         case CEE_MONO_CLASSCONST:
2985                                 token = read32 (td.ip + 1);
2986                                 td.ip += 5;
2987                                 ADD_CODE(&td, MINT_MONO_LDPTR);
2988                                 ADD_CODE(&td, get_data_item_index (&td, mono_method_get_wrapper_data (method, token)));
2989                                 td.sp [0].type = STACK_TYPE_I;
2990                                 ++td.sp;
2991                                 break;
2992                         case CEE_MONO_OBJADDR:
2993                                 CHECK_STACK (&td, 1);
2994                                 ++td.ip;
2995                                 td.sp[-1].type = STACK_TYPE_MP;
2996                                 /* do nothing? */
2997                                 break;
2998                         case CEE_MONO_NEWOBJ:
2999                                 token = read32 (td.ip + 1);
3000                                 td.ip += 5;
3001                                 ADD_CODE(&td, MINT_MONO_NEWOBJ);
3002                                 ADD_CODE(&td, get_data_item_index (&td, mono_method_get_wrapper_data (method, token)));
3003                                 td.sp [0].type = STACK_TYPE_O;
3004                                 ++td.sp;
3005                                 break;
3006                         case CEE_MONO_RETOBJ:
3007                                 CHECK_STACK (&td, 1);
3008                                 token = read32 (td.ip + 1);
3009                                 td.ip += 5;
3010                                 ADD_CODE(&td, MINT_MONO_RETOBJ);
3011                                 td.sp--;
3012
3013                                 klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
3014                                 
3015                                 /*stackval_from_data (signature->ret, frame->retval, sp->data.vt, signature->pinvoke);*/
3016
3017                                 if (td.sp > td.stack)
3018                                         g_warning ("CEE_MONO_RETOBJ: more values on stack: %d", td.sp-td.stack);
3019                                 break;
3020                         case CEE_MONO_LDNATIVEOBJ:
3021                                 token = read32 (td.ip + 1);
3022                                 td.ip += 5;
3023                                 klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
3024                                 g_assert(klass->valuetype);
3025                                 SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_MP);
3026                                 break;
3027                         case CEE_MONO_TLS: {
3028                                 gint32 key = read32 (td.ip + 1);
3029                                 td.ip += 5;
3030                                 g_assert (key < TLS_KEY_NUM);
3031                                 ADD_CODE (&td, MINT_MONO_TLS);
3032                                 WRITE32 (&td, &key);
3033                                 PUSH_SIMPLE_TYPE (&td, STACK_TYPE_MP);
3034                                 break;
3035                         }
3036                         case CEE_MONO_ATOMIC_STORE_I4:
3037                                 CHECK_STACK (&td, 2);
3038                                 SIMPLE_OP (td, MINT_MONO_ATOMIC_STORE_I4);
3039                                 td.sp -= 2;
3040                                 td.ip++;
3041                                 break;
3042                         case CEE_MONO_SAVE_LMF:
3043                         case CEE_MONO_RESTORE_LMF:
3044                         case CEE_MONO_NOT_TAKEN:
3045                                 ++td.ip;
3046                                 break;
3047                         case CEE_MONO_LDPTR_INT_REQ_FLAG:
3048                                 ADD_CODE (&td, MINT_MONO_LDPTR);
3049                                 ADD_CODE (&td, get_data_item_index (&td, mono_thread_interruption_request_flag ()));
3050                                 PUSH_TYPE (&td, STACK_TYPE_MP, NULL);
3051                                 ++td.ip;
3052                                 break;
3053                         case CEE_MONO_JIT_ATTACH:
3054                                 ADD_CODE (&td, MINT_MONO_JIT_ATTACH);
3055                                 ++td.ip;
3056                                 break;
3057                         case CEE_MONO_JIT_DETACH:
3058                                 ADD_CODE (&td, MINT_MONO_JIT_DETACH);
3059                                 ++td.ip;
3060                                 break;
3061                         default:
3062                                 g_error ("transform.c: Unimplemented opcode: 0xF0 %02x at 0x%x\n", *td.ip, td.ip-header->code);
3063                         }
3064                         break;
3065 #if 0
3066                 case CEE_PREFIX7:
3067                 case CEE_PREFIX6:
3068                 case CEE_PREFIX5:
3069                 case CEE_PREFIX4:
3070                 case CEE_PREFIX3:
3071                 case CEE_PREFIX2:
3072                 case CEE_PREFIXREF: ves_abort(); break;
3073 #endif
3074                 /*
3075                  * Note: Exceptions thrown when executing a prefixed opcode need
3076                  * to take into account the number of prefix bytes (usually the
3077                  * throw point is just (ip - n_prefix_bytes).
3078                  */
3079                 case CEE_PREFIX1: 
3080                         ++td.ip;
3081                         switch (*td.ip) {
3082 #if 0
3083                         case CEE_ARGLIST: ves_abort(); break;
3084 #endif
3085                         case CEE_CEQ:
3086                                 CHECK_STACK(&td, 2);
3087                                 if (td.sp [-1].type == STACK_TYPE_O || td.sp [-1].type == STACK_TYPE_MP)
3088                                         ADD_CODE(&td, MINT_CEQ_I4 + STACK_TYPE_I - STACK_TYPE_I4);
3089                                 else
3090                                         ADD_CODE(&td, MINT_CEQ_I4 + td.sp [-1].type - STACK_TYPE_I4);
3091                                 --td.sp;
3092                                 SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
3093                                 ++td.ip;
3094                                 break;
3095                         case CEE_CGT:
3096                                 CHECK_STACK(&td, 2);
3097                                 if (td.sp [-1].type == STACK_TYPE_O || td.sp [-1].type == STACK_TYPE_MP)
3098                                         ADD_CODE(&td, MINT_CGT_I4 + STACK_TYPE_I - STACK_TYPE_I4);
3099                                 else
3100                                         ADD_CODE(&td, MINT_CGT_I4 + td.sp [-1].type - STACK_TYPE_I4);
3101                                 --td.sp;
3102                                 SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
3103                                 ++td.ip;
3104                                 break;
3105                         case CEE_CGT_UN:
3106                                 CHECK_STACK(&td, 2);
3107                                 if (td.sp [-1].type == STACK_TYPE_O || td.sp [-1].type == STACK_TYPE_MP)
3108                                         ADD_CODE(&td, MINT_CGT_UN_I4 + STACK_TYPE_I - STACK_TYPE_I4);
3109                                 else
3110                                         ADD_CODE(&td, MINT_CGT_UN_I4 + td.sp [-1].type - STACK_TYPE_I4);
3111                                 --td.sp;
3112                                 SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
3113                                 ++td.ip;
3114                                 break;
3115                         case CEE_CLT:
3116                                 CHECK_STACK(&td, 2);
3117                                 if (td.sp [-1].type == STACK_TYPE_O || td.sp [-1].type == STACK_TYPE_MP)
3118                                         ADD_CODE(&td, MINT_CLT_I4 + STACK_TYPE_I - STACK_TYPE_I4);
3119                                 else
3120                                         ADD_CODE(&td, MINT_CLT_I4 + td.sp [-1].type - STACK_TYPE_I4);
3121                                 --td.sp;
3122                                 SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
3123                                 ++td.ip;
3124                                 break;
3125                         case CEE_CLT_UN:
3126                                 CHECK_STACK(&td, 2);
3127                                 if (td.sp [-1].type == STACK_TYPE_O || td.sp [-1].type == STACK_TYPE_MP)
3128                                         ADD_CODE(&td, MINT_CLT_UN_I4 + STACK_TYPE_I - STACK_TYPE_I4);
3129                                 else
3130                                         ADD_CODE(&td, MINT_CLT_UN_I4 + td.sp [-1].type - STACK_TYPE_I4);
3131                                 --td.sp;
3132                                 SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_I4);
3133                                 ++td.ip;
3134                                 break;
3135                         case CEE_LDVIRTFTN: /* fallthrough */
3136                         case CEE_LDFTN: {
3137                                 MonoMethod *m;
3138                                 if (*td.ip == CEE_LDVIRTFTN) {
3139                                         CHECK_STACK (&td, 1);
3140                                         --td.sp;
3141                                 }
3142                                 token = read32 (td.ip + 1);
3143                                 if (method->wrapper_type != MONO_WRAPPER_NONE)
3144                                         m = (MonoMethod *)mono_method_get_wrapper_data (method, token);
3145                                 else 
3146                                         m = mono_get_method_full (image, token, NULL, generic_context);
3147
3148                                 if (method->wrapper_type == MONO_WRAPPER_NONE && m->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
3149                                         m = mono_marshal_get_synchronized_wrapper (m);
3150
3151                                 ADD_CODE(&td, *td.ip == CEE_LDFTN ? MINT_LDFTN : MINT_LDVIRTFTN);
3152                                 ADD_CODE(&td, get_data_item_index (&td, mono_interp_get_runtime_method (domain, m, &error)));
3153                                 mono_error_cleanup (&error); /* FIXME: don't swallow the error */
3154                                 td.ip += 5;
3155                                 PUSH_SIMPLE_TYPE (&td, STACK_TYPE_F);
3156                                 break;
3157                         }
3158                         case CEE_LDARG:
3159                                 load_arg (&td, read16 (td.ip + 1));
3160                                 td.ip += 3;
3161                                 break;
3162                         case CEE_LDARGA: {
3163                                 int n = read16 (td.ip + 1);
3164                                 ADD_CODE (&td, MINT_LDARGA);
3165                                 ADD_CODE (&td, td.rtm->arg_offsets [n]); /* FIX for large offsets */
3166                                 PUSH_SIMPLE_TYPE(&td, STACK_TYPE_MP);
3167                                 td.ip += 3;
3168                                 break;
3169                         }
3170                         case CEE_STARG:
3171                                 store_arg (&td, read16 (td.ip + 1));
3172                                 td.ip += 3;
3173                                 break;
3174                         case CEE_LDLOC:
3175                                 load_local (&td, read16 (td.ip + 1));
3176                                 td.ip += 3;
3177                                 break;
3178                         case CEE_LDLOCA:
3179                                 ADD_CODE(&td, MINT_LDLOCA_S);
3180                                 ADD_CODE(&td, td.rtm->local_offsets [read16 (td.ip + 1)]);
3181                                 PUSH_SIMPLE_TYPE(&td, STACK_TYPE_MP);
3182                                 td.ip += 3;
3183                                 break;
3184                         case CEE_STLOC:
3185                                 store_local (&td, read16 (td.ip + 1));
3186                                 td.ip += 3;
3187                                 break;
3188                         case CEE_LOCALLOC:
3189                                 CHECK_STACK (&td, 1);
3190 #if SIZEOF_VOID_P == 8
3191                                 if (td.sp [-1].type == STACK_TYPE_I8)
3192                                         ADD_CODE(&td, MINT_CONV_I4_I8);
3193 #endif                          
3194                                 ADD_CODE(&td, MINT_LOCALLOC);
3195                                 if (td.sp != td.stack + 1)
3196                                         g_warning("CEE_LOCALLOC: stack not empty");
3197                                 ++td.ip;
3198                                 SET_SIMPLE_TYPE(td.sp - 1, STACK_TYPE_MP);
3199                                 break;
3200 #if 0
3201                         case CEE_UNUSED57: ves_abort(); break;
3202 #endif
3203                         case CEE_ENDFILTER:
3204                                 ADD_CODE (&td, MINT_ENDFILTER);
3205                                 ++td.ip;
3206                                 break;
3207                         case CEE_UNALIGNED_:
3208                                 ++td.ip;
3209                                 /* FIX: should do something? */;
3210                                 break;
3211                         case CEE_VOLATILE_:
3212                                 ++td.ip;
3213                                 /* FIX: should do something? */;
3214                                 break;
3215                         case CEE_TAIL_:
3216                                 ++td.ip;
3217                                 /* FIX: should do something? */;
3218                                 break;
3219                         case CEE_INITOBJ:
3220                                 CHECK_STACK(&td, 1);
3221                                 token = read32 (td.ip + 1);
3222                                 klass = mini_get_class (method, token, generic_context);
3223                                 if (klass->valuetype) {
3224                                         ADD_CODE (&td, MINT_INITOBJ);
3225                                         i32 = mono_class_value_size (klass, NULL);
3226                                         WRITE32 (&td, &i32);
3227                                 } else {
3228                                         ADD_CODE (&td, MINT_LDNULL);
3229                                         ADD_CODE (&td, MINT_STIND_REF);
3230                                 }
3231                                 td.ip += 5;
3232                                 --td.sp;
3233                                 break;
3234                         case CEE_CPBLK:
3235                                 CHECK_STACK(&td, 3);
3236                                 /* FIX? convert length to I8? */
3237                                 ADD_CODE(&td, MINT_CPBLK);
3238                                 td.sp -= 3;
3239                                 ++td.ip;
3240                                 break;
3241                         case CEE_READONLY_:
3242                                 readonly = TRUE;
3243                                 td.ip += 1;
3244                                 break;
3245                         case CEE_CONSTRAINED_:
3246                                 token = read32 (td.ip + 1);
3247                                 constrained_class = mini_get_class (method, token, generic_context);
3248                                 mono_class_init (constrained_class);
3249                                 td.ip += 5;
3250                                 break;
3251                         case CEE_INITBLK:
3252                                 CHECK_STACK(&td, 3);
3253                                 ADD_CODE(&td, MINT_INITBLK);
3254                                 td.sp -= 3;
3255                                 td.ip += 1;
3256                                 break;
3257 #if 0
3258                         case CEE_NO_:
3259                                 /* FIXME: implement */
3260                                 ip += 2;
3261                                 break;
3262 #endif
3263                         case CEE_RETHROW:
3264                                 SIMPLE_OP (td, MINT_RETHROW);
3265                                 generating_code = 0;
3266                                 break;
3267                         case CEE_SIZEOF: {
3268                                 gint32 size;
3269                                 token = read32 (td.ip + 1);
3270                                 td.ip += 5;
3271                                 if (mono_metadata_token_table (token) == MONO_TABLE_TYPESPEC && !image_is_dynamic (method->klass->image) && !generic_context) {
3272                                         int align;
3273                                         MonoType *type = mono_type_create_from_typespec (image, token);
3274                                         size = mono_type_size (type, &align);
3275                                 } else {
3276                                         int align;
3277                                         MonoClass *szclass = mini_get_class (method, token, generic_context);
3278                                         mono_class_init (szclass);
3279 #if 0
3280                                         if (!szclass->valuetype)
3281                                                 THROW_EX (mono_exception_from_name (mono_defaults.corlib, "System", "InvalidProgramException"), ip - 5);
3282 #endif
3283                                         size = mono_type_size (&szclass->byval_arg, &align);
3284                                 } 
3285                                 ADD_CODE(&td, MINT_LDC_I4);
3286                                 WRITE32(&td, &size);
3287                                 PUSH_SIMPLE_TYPE(&td, STACK_TYPE_I4);
3288                                 break;
3289                         }
3290 #if 0
3291                         case CEE_REFANYTYPE: ves_abort(); break;
3292 #endif
3293                         default:
3294                                 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);
3295                         }
3296                         break;
3297                 default:
3298                         g_error ("transform.c: Unimplemented opcode: %02x at 0x%x\n", *td.ip, td.ip-header->code);
3299                 }
3300
3301                 if (td.new_ip - td.new_code != new_in_start_offset) 
3302                         td.last_new_ip = td.new_code + new_in_start_offset;
3303                 else if (td.is_bb_start [td.in_start - td.il_code])
3304                         td.is_bb_start [td.ip - td.il_code] = 1;
3305                         
3306                 td.last_ip = td.in_start;
3307         }
3308
3309         if (mono_interp_traceopt) {
3310                 const guint16 *p = td.new_code;
3311                 printf("Runtime method: %p, VT stack size: %d\n", rtm, td.max_vt_sp);
3312                 printf("Calculated stack size: %d, stated size: %d\n", td.max_stack_height, header->max_stack);
3313                 while (p < td.new_ip) {
3314                         p = mono_interp_dis_mintop(td.new_code, p);
3315                         printf("\n");
3316                 }
3317         }
3318         g_assert (td.max_stack_height <= (header->max_stack + 1));
3319
3320         int code_len = td.new_ip - td.new_code;
3321
3322         rtm->clauses = mono_domain_alloc0 (domain, header->num_clauses * sizeof (MonoExceptionClause));
3323         memcpy (rtm->clauses, header->clauses, header->num_clauses * sizeof(MonoExceptionClause));
3324         rtm->code = mono_domain_alloc0 (domain, (td.new_ip - td.new_code) * sizeof (gushort));
3325         memcpy (rtm->code, td.new_code, (td.new_ip - td.new_code) * sizeof(gushort));
3326         g_free (td.new_code);
3327         rtm->new_body_start = rtm->code + body_start_offset;
3328         rtm->num_clauses = header->num_clauses;
3329         for (i = 0; i < header->num_clauses; i++) {
3330                 MonoExceptionClause *c = rtm->clauses + i;
3331                 int end_off = c->try_offset + c->try_len;
3332                 c->try_offset = td.in_offsets [c->try_offset];
3333                 c->try_len = td.in_offsets [end_off] - c->try_offset;
3334                 end_off = c->handler_offset + c->handler_len;
3335                 c->handler_offset = td.in_offsets [c->handler_offset];
3336                 c->handler_len = td.in_offsets [end_off] - c->handler_offset;
3337                 if (c->flags & MONO_EXCEPTION_CLAUSE_FILTER)
3338                         c->data.filter_offset = td.in_offsets [c->data.filter_offset];
3339         }
3340         rtm->vt_stack_size = td.max_vt_sp;
3341         rtm->alloca_size = rtm->locals_size + rtm->args_size + rtm->vt_stack_size + rtm->stack_size;
3342         rtm->data_items = mono_domain_alloc0 (domain, td.n_data_items * sizeof (td.data_items [0]));
3343         memcpy (rtm->data_items, td.data_items, td.n_data_items * sizeof (td.data_items [0]));
3344
3345         /* Save debug info */
3346         interp_save_debug_info (rtm, header, &td, line_numbers);
3347
3348         /* Create a MonoJitInfo for the interpreted method by creating the interpreter IR as the native code. */
3349         int jinfo_len = mono_jit_info_size (0, header->num_clauses, 0);
3350         MonoJitInfo *jinfo = (MonoJitInfo *)mono_domain_alloc0 (domain, jinfo_len);
3351         rtm->jinfo = jinfo;
3352         mono_jit_info_init (jinfo, method, (guint8*)rtm->code, code_len, 0, header->num_clauses, 0);
3353         for (i = 0; i < jinfo->num_clauses; ++i) {
3354                 MonoJitExceptionInfo *ei = &jinfo->clauses [i];
3355                 MonoExceptionClause *c = rtm->clauses + i;
3356
3357                 ei->flags = c->flags;
3358                 ei->try_start = rtm->code + c->try_offset;
3359                 ei->try_end = rtm->code + c->try_offset + c->try_len;
3360                 ei->handler_start = rtm->code + c->handler_offset;
3361                 if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER || ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
3362                 } else {
3363                         ei->data.catch_class = c->data.catch_class;
3364                 }
3365         }
3366
3367         g_free (td.in_offsets);
3368         g_free (td.forward_refs);
3369         for (i = 0; i < header->code_size; ++i)
3370                 g_free (td.stack_state [i]);
3371         g_free (td.stack_state);
3372         g_free (td.stack_height);
3373         g_free (td.vt_stack_size);
3374         g_free (td.data_items);
3375         g_free (td.stack);
3376         g_hash_table_destroy (td.data_hash);
3377         g_free (td.clause_indexes);
3378         g_array_free (line_numbers, TRUE);
3379 }
3380
3381 static mono_mutex_t calc_section;
3382
3383 void 
3384 mono_interp_transform_init (void)
3385 {
3386         mono_os_mutex_init_recursive(&calc_section);
3387 }
3388
3389 MonoException *
3390 mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *context)
3391 {
3392         int i, align, size, offset;
3393         MonoMethod *method = runtime_method->method;
3394         MonoImage *image = method->klass->image;
3395         MonoMethodHeader *header = mono_method_get_header (method);
3396         MonoMethodSignature *signature = mono_method_signature (method);
3397         register const unsigned char *ip, *end;
3398         const MonoOpcode *opcode;
3399         MonoMethod *m;
3400         MonoClass *class;
3401         MonoDomain *domain = mono_domain_get ();
3402         unsigned char *is_bb_start;
3403         int in;
3404         MonoVTable *method_class_vt;
3405         int backwards;
3406         MonoGenericContext *generic_context = NULL;
3407
3408         // g_printerr ("TRANSFORM(0x%016lx): begin %s::%s\n", mono_thread_current (), method->klass->name, method->name);
3409         method_class_vt = mono_class_vtable (domain, runtime_method->method->klass);
3410         if (!method_class_vt->initialized) {
3411                 MonoError error;
3412                 jmp_buf env;
3413                 MonoInvocation *last_env_frame = context->env_frame;
3414                 jmp_buf *old_env = context->current_env;
3415                 error_init (&error);
3416
3417                 if (setjmp(env)) {
3418                         MonoException *failed = context->env_frame->ex;
3419                         context->env_frame->ex = NULL;
3420                         context->env_frame = last_env_frame;
3421                         context->current_env = old_env;
3422                         return failed;
3423                 }
3424                 context->env_frame = context->current_frame;
3425                 context->current_env = &env;
3426                 mono_runtime_class_init_full (method_class_vt, &error);
3427                 if (!mono_error_ok (&error)) {
3428                         return mono_error_convert_to_exception (&error);
3429                 }
3430                 context->env_frame = last_env_frame;
3431                 context->current_env = old_env;
3432         }
3433
3434         mono_profiler_method_jit (method); /* sort of... */
3435
3436         if (mono_method_signature (method)->is_inflated)
3437                 generic_context = mono_method_get_context (method);
3438         else {
3439                 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
3440                 if (generic_container)
3441                         generic_context = &generic_container->context;
3442         }
3443
3444         if (method->iflags & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
3445                 MonoMethod *nm = NULL;
3446                 mono_os_mutex_lock(&calc_section);
3447                 if (runtime_method->transformed) {
3448                         mono_os_mutex_unlock(&calc_section);
3449                         mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_OK);
3450                         return NULL;
3451                 }
3452
3453                 /* assumes all internal calls with an array this are built in... */
3454                 if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL && (! mono_method_signature (method)->hasthis || method->klass->rank == 0)) {
3455                         nm = mono_marshal_get_native_wrapper (method, TRUE, FALSE);
3456                         signature = mono_method_signature (nm);
3457                 } else {
3458                         const char *name = method->name;
3459                         if (method->klass->parent == mono_defaults.multicastdelegate_class) {
3460                                 if (*name == '.' && (strcmp (name, ".ctor") == 0)) {
3461                                         MonoJitICallInfo *mi = mono_find_jit_icall_by_name ("ves_icall_mono_delegate_ctor");
3462                                         g_assert (mi);
3463                                         char *wrapper_name = g_strdup_printf ("__icall_wrapper_%s", mi->name);
3464                                         nm = mono_marshal_get_icall_wrapper (mi->sig, wrapper_name, mi->func, TRUE);
3465                                 } else if (*name == 'I' && (strcmp (name, "Invoke") == 0)) {
3466                                         nm = mono_marshal_get_delegate_invoke (method, NULL);
3467                                 } else if (*name == 'B' && (strcmp (name, "BeginInvoke") == 0)) {
3468                                         nm = mono_marshal_get_delegate_begin_invoke (method);
3469                                 } else if (*name == 'E' && (strcmp (name, "EndInvoke") == 0)) {
3470                                         nm = mono_marshal_get_delegate_end_invoke (method);
3471                                 }
3472                         }
3473                         if (nm == NULL) {
3474                                 runtime_method->code = g_malloc(sizeof(short));
3475                                 runtime_method->code[0] = MINT_CALLRUN;
3476                         }
3477                 }
3478                 if (nm == NULL) {
3479                         runtime_method->stack_size = sizeof (stackval); /* for tracing */
3480                         runtime_method->alloca_size = runtime_method->stack_size;
3481                         runtime_method->transformed = TRUE;
3482                         mono_os_mutex_unlock(&calc_section);
3483                         mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_OK);
3484                         return NULL;
3485                 }
3486                 method = nm;
3487                 header = mono_method_get_header (nm);
3488                 mono_os_mutex_unlock(&calc_section);
3489         } else if (method->klass == mono_defaults.array_class) {
3490                 if (!strcmp (method->name, "UnsafeMov")) {
3491                         mono_os_mutex_lock (&calc_section);
3492                         if (!runtime_method->transformed) {
3493                                 runtime_method->code = g_malloc (sizeof (short));
3494                                 runtime_method->code[0] = MINT_CALLRUN;
3495                                 runtime_method->stack_size = sizeof (stackval); /* for tracing */
3496                                 runtime_method->alloca_size = runtime_method->stack_size;
3497                                 runtime_method->transformed = TRUE;
3498                         }
3499                         mono_os_mutex_unlock(&calc_section);
3500                         mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_OK);
3501                         return NULL;
3502                 } else if (!strcmp (method->name, "UnsafeStore)")) {
3503                         g_error ("TODO");
3504                 } else if (!strcmp (method->name, "UnsafeLoad)")) {
3505                         g_error ("TODO");
3506                 }
3507         }
3508         g_assert ((signature->param_count + signature->hasthis) < 1000);
3509         g_assert (header->max_stack < 10000);
3510         /* intern the strings in the method. */
3511         ip = header->code;
3512         end = ip + header->code_size;
3513
3514         is_bb_start = g_malloc0(header->code_size);
3515         is_bb_start [0] = 1;
3516         while (ip < end) {
3517                 in = *ip;
3518                 if (in == 0xfe) {
3519                         ip++;
3520                         in = *ip + 256;
3521                 }
3522                 else if (in == 0xf0) {
3523                         ip++;
3524                         in = *ip + MONO_CEE_MONO_ICALL;
3525                 }
3526                 opcode = &mono_opcodes [in];
3527                 switch (opcode->argument) {
3528                 case MonoInlineNone:
3529                         ++ip;
3530                         break;
3531                 case MonoInlineString:
3532                         if (method->wrapper_type == MONO_WRAPPER_NONE)
3533                                 mono_ldstr (domain, image, mono_metadata_token_index (read32 (ip + 1)));
3534                         ip += 5;
3535                         break;
3536                 case MonoInlineType:
3537                         if (method->wrapper_type == MONO_WRAPPER_NONE) {
3538                                 class = mini_get_class (method, read32 (ip + 1), generic_context);
3539                                 mono_class_init (class);
3540                                 /* quick fix to not do this for the fake ptr classes - probably should not be getting the vtable at all here */
3541 #if 0
3542                                 g_error ("FIXME: interface method lookup: %s (in method %s)", class->name, method->name);
3543                                 if (!(class->flags & TYPE_ATTRIBUTE_INTERFACE) && class->interface_offsets != NULL)
3544                                         mono_class_vtable (domain, class);
3545 #endif
3546                         }
3547                         ip += 5;
3548                         break;
3549                 case MonoInlineMethod:
3550                         if (method->wrapper_type == MONO_WRAPPER_NONE && *ip != CEE_CALLI) {
3551                                 m = mono_get_method_full (image, read32 (ip + 1), NULL, generic_context);
3552                                 if (m == NULL) {
3553                                         g_free (is_bb_start);
3554                                         g_error ("FIXME: where to get method and class string?"); 
3555                                         return NULL;
3556                                         // return mono_get_exception_missing_method ();
3557                                 }
3558                                 mono_class_init (m->klass);
3559                                 if (!mono_class_is_interface (m->klass))
3560                                         mono_class_vtable (domain, m->klass);
3561                         }
3562                         ip += 5;
3563                         break;
3564                 case MonoInlineField:
3565                 case MonoInlineSig:
3566                 case MonoInlineI:
3567                 case MonoInlineTok:
3568                 case MonoShortInlineR:
3569                         ip += 5;
3570                         break;
3571                 case MonoInlineBrTarget:
3572                         offset = read32 (ip + 1);
3573                         ip += 5;
3574                         backwards = offset < 0;
3575                         offset += ip - header->code;
3576                         g_assert (offset >= 0 && offset < header->code_size);
3577                         is_bb_start [offset] |= backwards ? 2 : 1;
3578                         break;
3579                 case MonoShortInlineBrTarget:
3580                         offset = ((gint8 *)ip) [1];
3581                         ip += 2;
3582                         backwards = offset < 0;
3583                         offset += ip - header->code;
3584                         g_assert (offset >= 0 && offset < header->code_size);
3585                         is_bb_start [offset] |= backwards ? 2 : 1;
3586                         break;
3587                 case MonoInlineVar:
3588                         ip += 3;
3589                         break;
3590                 case MonoShortInlineVar:
3591                 case MonoShortInlineI:
3592                         ip += 2;
3593                         break;
3594                 case MonoInlineSwitch: {
3595                         guint32 n;
3596                         const unsigned char *next_ip;
3597                         ++ip;
3598                         n = read32 (ip);
3599                         ip += 4;
3600                         next_ip = ip + 4 * n;
3601                         for (i = 0; i < n; i++) {
3602                                 offset = read32 (ip);
3603                                 backwards = offset < 0;
3604                                 offset += next_ip - header->code;
3605                                 g_assert (offset >= 0 && offset < header->code_size);
3606                                 is_bb_start [offset] |= backwards ? 2 : 1;
3607                                 ip += 4;
3608                         }
3609                         break;
3610                 }
3611                 case MonoInlineR:
3612                 case MonoInlineI8:
3613                         ip += 9;
3614                         break;
3615                 default:
3616                         g_assert_not_reached ();
3617                 }
3618         }
3619         // g_printerr ("TRANSFORM(0x%016lx): end %s::%s\n", mono_thread_current (), method->klass->name, method->name);
3620
3621         /* the rest needs to be locked so it is only done once */
3622         mono_os_mutex_lock(&calc_section);
3623         if (runtime_method->transformed) {
3624                 mono_os_mutex_unlock(&calc_section);
3625                 g_free (is_bb_start);
3626                 mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_OK);
3627                 return NULL;
3628         }
3629
3630         runtime_method->local_offsets = g_malloc (header->num_locals * sizeof(guint32));
3631         runtime_method->stack_size = (sizeof (stackval)) * (header->max_stack + 2); /* + 1 for returns of called functions  + 1 for 0-ing in trace*/
3632         runtime_method->stack_size = (runtime_method->stack_size + 7) & ~7;
3633         offset = 0;
3634         for (i = 0; i < header->num_locals; ++i) {
3635                 size = mono_type_size (header->locals [i], &align);
3636                 offset += align - 1;
3637                 offset &= ~(align - 1);
3638                 runtime_method->local_offsets [i] = offset;
3639                 offset += size;
3640         }
3641         offset = (offset + 7) & ~7;
3642         runtime_method->locals_size = offset;
3643         g_assert (runtime_method->locals_size < 65536);
3644         offset = 0;
3645         runtime_method->arg_offsets = g_malloc ((!!signature->hasthis + signature->param_count) * sizeof(guint32));
3646
3647         if (signature->hasthis) {
3648                 g_assert (!signature->pinvoke);
3649                 size = mono_type_stack_size (&method->klass->byval_arg, &align);
3650                 offset += align - 1;
3651                 offset &= ~(align - 1);
3652                 runtime_method->arg_offsets [0] = offset;
3653                 offset += size;
3654         }
3655
3656         for (i = 0; i < signature->param_count; ++i) {
3657                 if (signature->pinvoke) {
3658                         guint32 dummy;
3659                         size = mono_type_native_stack_size (signature->params [i], &dummy);
3660                         align = 8;
3661                 }
3662                 else
3663                         size = mono_type_stack_size (signature->params [i], &align);
3664                 offset += align - 1;
3665                 offset &= ~(align - 1);
3666                 runtime_method->arg_offsets [i + !!signature->hasthis] = offset;
3667                 offset += size;
3668         }
3669         offset = (offset + 7) & ~7;
3670         runtime_method->args_size = offset;
3671         g_assert (runtime_method->args_size < 10000);
3672
3673         generate (method, runtime_method, is_bb_start, generic_context);
3674
3675         g_free (is_bb_start);
3676
3677         mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_OK);
3678         runtime_method->transformed = TRUE;
3679         mono_os_mutex_unlock(&calc_section);
3680
3681         return NULL;
3682 }
3683