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