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