3 * transform CIL into different opcodes for more
4 * efficient interpretation
6 * Written by Bernie Solomon (bernard@ugsolutions.com)
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>
22 #include "interp-internals.h"
25 // TODO: export from marshal.c
26 MonoDelegate
* mono_ftnptr_to_delegate (MonoClass
*klass
, gpointer ftn
);
40 MonoMethodHeader
*header
;
42 const unsigned char *il_code
;
43 const unsigned char *ip
;
44 const unsigned char *last_ip
;
45 const unsigned char *in_start
;
49 StackInfo
**stack_state
;
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
;
60 unsigned int max_stack_height
;
62 unsigned int max_vt_sp
;
66 GHashTable
*data_hash
;
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
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
94 #define STACK_TYPE_I STACK_TYPE_I4
97 static int stack_type
[] = {
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*/
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) \
125 if ((td)->new_ip + (n) > (td)->new_code_end) \
129 #define ADD_CODE(td, n) \
131 if ((td)->new_ip == (td)->new_code_end) \
133 *(td)->new_ip++ = (n); \
136 #define CHECK_STACK(td, n) \
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); \
145 #define ENSURE_I4(td, sp_off) \
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); \
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
;
165 offset
= td
->in_offsets
[target
] - (td
->new_ip
- td
->new_code
);
166 if (offset
>= -32768) {
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
;
174 if (td
->header
->code_size
<= 25000) /* FIX to be precise somehow? */
177 if (shorten_branch
) {
178 ADD_CODE(td
, short_op
);
179 ADD_CODE(td
, offset
);
181 ADD_CODE(td
, long_op
);
182 ADD_CODE(td
, * (unsigned short *)(&offset
));
183 ADD_CODE(td
, * ((unsigned short *)&offset
+ 1));
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
;
195 handle_branch (td
, short_op
, long_op
, offset
);
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
;
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
);
218 handle_branch (td
, short_op
, long_op
, offset
);
222 unary_arith_op(TransformData
*td
, int mint_op
)
224 int op
= mint_op
+ td
->sp
[-1].type
- STACK_TYPE_I4
;
230 binary_arith_op(TransformData
*td
, int mint_op
)
232 int type1
= td
->sp
[-2].type
;
233 int type2
= td
->sp
[-1].type
;
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
;
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
;
262 binary_int_op(TransformData
*td
, int mint_op
)
264 int op
= mint_op
+ td
->sp
[-1].type
- STACK_TYPE_I4
;
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
);
273 shift_op(TransformData
*td
, int mint_op
)
275 int op
= mint_op
+ td
->sp
[-2].type
- STACK_TYPE_I4
;
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
,
287 mint_type(MonoType
*type
)
292 switch (type
->type
) {
296 case MONO_TYPE_BOOLEAN
:
308 #if SIZEOF_VOID_P == 4
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
:
328 case MONO_TYPE_VALUETYPE
:
329 if (type
->data
.klass
->enumtype
) {
330 type
= mono_class_enum_basetype (type
->data
.klass
);
334 case MONO_TYPE_GENERICINST
:
335 type
= &type
->data
.generic_class
->container_class
->byval_arg
;
338 g_warning ("got type 0x%02x", type
->type
);
339 g_assert_not_reached ();
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) \
361 #define SET_TYPE(s, ty, k) \
368 #define PUSH_SIMPLE_TYPE(td, ty) \
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); \
378 #define PUSH_TYPE(td, ty, k) \
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); \
388 #define PUSH_VT(td, size) \
390 (td)->vt_sp += ((size) + 7) & ~7; \
391 if ((td)->vt_sp > (td)->max_vt_sp) \
392 (td)->max_vt_sp = (td)->vt_sp; \
395 #define POP_VT(td, size) \
397 (td)->vt_sp -= ((size) + 7) & ~7; \
400 #if NO_UNALIGNED_ACCESS
401 #define WRITE32(td, v) \
403 ENSURE_CODE(td, 2); \
404 * (guint16 *)((td)->new_ip) = * (guint16 *)(v); \
405 * ((guint16 *)((td)->new_ip) + 1) = * ((guint16 *)(v) + 1); \
409 #define WRITE64(td, v) \
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); \
419 #define WRITE32(td, v) \
421 ENSURE_CODE(td, 2); \
422 * (guint32 *)((td)->new_ip) = * (guint32 *)(v); \
426 #define WRITE64(td, v) \
428 ENSURE_CODE(td, 4); \
429 * (guint64 *)((td)->new_ip) = * (guint64 *)(v); \
436 load_arg(TransformData
*td
, int n
)
439 MonoClass
*klass
= NULL
;
442 gboolean hasthis
= mono_method_signature (td
->method
)->hasthis
;
443 if (hasthis
&& n
== 0)
444 type
= &td
->method
->klass
->byval_arg
;
446 type
= mono_method_signature (td
->method
)->params
[hasthis
? n
- 1 : n
];
448 mt
= mint_type (type
);
449 if (mt
== MINT_TYPE_VT
) {
451 klass
= mono_class_from_mono_type (type
);
452 if (mono_method_signature (td
->method
)->pinvoke
)
453 size
= mono_class_native_size (klass
, NULL
);
455 size
= mono_class_value_size (klass
, NULL
);
457 if (hasthis
&& n
== 0) {
459 ADD_CODE (td
, MINT_LDARG_P
);
460 ADD_CODE (td
, td
->rtm
->arg_offsets
[n
]); /* FIX for large offset */
464 ADD_CODE (td
, MINT_LDARG_VT
);
465 ADD_CODE (td
, td
->rtm
->arg_offsets
[n
]); /* FIX for large offset */
469 if (hasthis
&& n
== 0) {
471 ADD_CODE (td
, MINT_LDARG_P
);
472 ADD_CODE (td
, td
->rtm
->arg_offsets
[n
]); /* FIX for large offset */
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
);
485 store_arg(TransformData
*td
, int n
)
491 gboolean hasthis
= mono_method_signature (td
->method
)->hasthis
;
492 if (hasthis
&& n
== 0)
493 type
= &td
->method
->klass
->byval_arg
;
495 type
= mono_method_signature (td
->method
)->params
[n
- !!hasthis
];
497 mt
= mint_type (type
);
498 if (mt
== MINT_TYPE_VT
) {
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
);
504 size
= mono_class_value_size (klass
, NULL
);
505 ADD_CODE(td
, MINT_STARG_VT
);
506 ADD_CODE(td
, td
->rtm
->arg_offsets
[n
]);
508 if (td
->sp
[-1].type
== STACK_TYPE_VT
)
511 ADD_CODE(td
, MINT_STARG_I1
+ (mt
- MINT_TYPE_I1
));
512 ADD_CODE(td
, td
->rtm
->arg_offsets
[n
]);
518 store_inarg(TransformData
*td
, int n
)
521 gboolean hasthis
= mono_method_signature (td
->method
)->hasthis
;
522 if (hasthis
&& n
== 0)
523 type
= &td
->method
->klass
->byval_arg
;
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
);
533 if (mt
== MINT_TYPE_VT
) {
534 MonoClass
*klass
= mono_class_from_mono_type (type
);
536 if (mono_method_signature (td
->method
)->pinvoke
)
537 size
= mono_class_native_size (klass
, NULL
);
539 size
= mono_class_value_size (klass
, NULL
);
540 ADD_CODE(td
, MINT_STINARG_VT
);
544 ADD_CODE(td
, MINT_STINARG_I1
+ (mt
- MINT_TYPE_I1
));
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
);
560 ADD_CODE(td
, MINT_LDLOC_VT
);
561 ADD_CODE(td
, offset
); /*FIX for large offset */
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
;
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
);
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
];
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
;
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 */
605 if (td
->sp
[-1].type
== STACK_TYPE_VT
)
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 */
615 #define SIMPLE_OP(td, op) \
622 get_data_item_index (TransformData
*td
, void *ptr
)
624 gpointer p
= g_hash_table_lookup (td
->data_hash
, ptr
);
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
;
635 g_hash_table_insert (td
->data_hash
, ptr
, GUINT_TO_POINTER (index
+ 1));
640 jit_call_supported (MonoMethod
*method
, MonoMethodSignature
*sig
)
644 if (sig
->param_count
> 6)
648 if (method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
)
650 if (method
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
)
652 if (method
->is_inflated
)
654 if (method
->string_ctor
)
657 for (l
= jit_classes
; l
; l
= l
->next
) {
658 char *class_name
= l
->data
;
660 if (!strcmp (method
->klass
->name
, class_name
))
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
;
674 int virtual = *td
->ip
== CEE_CALLVIRT
;
675 int calli
= *td
->ip
== CEE_CALLI
|| *td
->ip
== CEE_MONO_CALLI_EXTRA_ARG
;
677 guint32 vt_stack_used
= 0;
678 guint32 vt_res_size
= 0;
683 guint32 token
= read32 (td
->ip
+ 1);
685 if (target_method
== NULL
) {
688 native
= (method
->wrapper_type
!= MONO_WRAPPER_DELEGATE_INVOKE
&& td
->sp
[-1].type
== STACK_TYPE_I
);
690 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
691 csignature
= (MonoMethodSignature
*)mono_method_get_wrapper_data (method
, token
);
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
;
702 if (method
->wrapper_type
== MONO_WRAPPER_NONE
)
703 target_method
= mono_get_method_full (image
, token
, NULL
, generic_context
);
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)
711 else if (strcmp (target_method
->name
, "get_Length") == 0)
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")) {
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 */
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
);
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
);
749 target_method
= mono_get_method_constrained_with_method (image
, target_method
, constrained_class
, generic_context
, &error
);
751 g_print (" : %s::%s. %s (%p)\n", target_method
->klass
->name
, target_method
->name
, mono_signature_full_name (target_method
->signature
), target_method
);
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
);
770 if (target_method
->klass
->valuetype
) {
773 /* Interface method */
776 mono_class_setup_vtable (constrained_class
);
777 ioffset
= mono_class_interface_offset (constrained_class
, target_method
->klass
);
779 g_error ("type load error: constrained_class");
780 slot
= mono_method_get_vtable_slot (target_method
);
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
);
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
) {
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
)
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 */
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 */
833 if (csignature
->hasthis
) {
835 ADD_CODE(td
, MINT_CKNULL
);
836 ADD_CODE (td
, MINT_POP
);
839 td
->sp
-= csignature
->param_count
+ csignature
->hasthis
;
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
) {
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
);
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
);
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
);
883 #if SIZEOF_VOID_P == 8
884 if (op
== MINT_LDLEN
)
885 ADD_CODE (td
, MINT_CONV_I4_I8
);
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
);
897 ADD_CODE(td
, native
? MINT_CALLI_NAT
: MINT_CALLI
);
899 ADD_CODE(td
, is_void
? MINT_VCALLVIRT
: MINT_CALLVIRT
);
901 ADD_CODE(td
, is_void
? MINT_VCALL
: MINT_CALL
);
904 ADD_CODE(td
, get_data_item_index (td
, (void *)csignature
));
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 */
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
;
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
;
928 int offset
, mt
, i
, i32
;
929 gboolean readonly
= FALSE
;
931 MonoClassField
*field
;
932 const unsigned char *end
;
933 int new_in_start_offset
;
934 int body_start_offset
;
938 int generating_code
= 1;
940 memset(&td
, 0, sizeof(td
));
943 td
.is_bb_start
= is_bb_start
;
944 td
.il_code
= header
->code
;
945 td
.code_size
= header
->code_size
;
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));
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]));
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
);
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
);
1021 while (td
.ip
< end
) {
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
];
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);
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
;
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
])
1073 if (mono_interp_traceopt
> 1) {
1074 printf("IL_%04lx %s %-10s -> IL_%04lx, sp %ld, %s %-12s vt_sp %u (max %u)\n",
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
);
1090 SIMPLE_OP(td
, MINT_BREAK
);
1096 load_arg (&td
, *td
.ip
- CEE_LDARG_0
);
1103 load_local (&td
, *td
.ip
- CEE_LDLOC_0
);
1110 store_local (&td
, *td
.ip
- CEE_STLOC_0
);
1114 load_arg (&td
, ((guint8
*)td
.ip
)[1]);
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
);
1127 store_arg (&td
, ((guint8
*)td
.ip
)[1]);
1131 load_local (&td
, ((guint8
*)td
.ip
)[1]);
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
);
1141 store_local (&td
, ((guint8
*)td
.ip
)[1]);
1145 SIMPLE_OP(td
, MINT_LDNULL
);
1146 PUSH_TYPE(&td
, STACK_TYPE_O
, NULL
);
1149 SIMPLE_OP(td
, MINT_LDC_I4_M1
);
1150 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I4
);
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
);
1158 SIMPLE_OP(td
, MINT_LDC_I4_0
);
1159 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I4
);
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
);
1168 SIMPLE_OP(td
, MINT_LDC_I4_1
);
1169 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I4
);
1179 SIMPLE_OP(td
, (*td
.ip
- CEE_LDC_I4_0
) + MINT_LDC_I4_0
);
1180 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I4
);
1183 ADD_CODE(&td
, MINT_LDC_I4_S
);
1184 ADD_CODE(&td
, ((gint8
*) td
.ip
) [1]);
1186 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I4
);
1189 i32
= read32 (td
.ip
+ 1);
1190 ADD_CODE(&td
, MINT_LDC_I4
);
1193 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I4
);
1196 gint64 val
= read64 (td
.ip
+ 1);
1197 ADD_CODE(&td
, MINT_LDC_I8
);
1200 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I8
);
1205 readr4 (td
.ip
+ 1, &val
);
1206 ADD_CODE(&td
, MINT_LDC_R4
);
1209 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_R8
);
1214 readr8 (td
.ip
+ 1, &val
);
1215 ADD_CODE(&td
, MINT_LDC_R8
);
1218 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_R8
);
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
);
1227 ADD_CODE(&td
, MINT_DUP_VT
);
1228 WRITE32(&td
, &size
);
1231 SIMPLE_OP(td
, MINT_DUP
);
1232 PUSH_TYPE(&td
, type
, klass
);
1236 CHECK_STACK(&td
, 1);
1237 SIMPLE_OP(td
, MINT_POP
);
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
);
1244 WRITE32(&td
, &size
);
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 */
1261 case CEE_CALLVIRT
: /* Fall through */
1262 case CEE_CALLI
: /* Fall through */
1264 interp_transform_call (&td
, method
, NULL
, domain
, generic_context
, is_bb_start
, body_start_offset
, constrained_class
, readonly
);
1265 constrained_class
= NULL
;
1271 if (signature
->ret
->type
!= MONO_TYPE_VOID
) {
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
);
1284 SIMPLE_OP(td
, signature
->ret
->type
== MONO_TYPE_VOID
? MINT_RET_VOID
: MINT_RET
);
1286 ADD_CODE(&td
, MINT_RET_VT
);
1287 WRITE32(&td
, &vt_size
);
1290 generating_code
= 0;
1294 handle_branch (&td
, MINT_BR_S
, MINT_BR
, 5 + read32 (td
.ip
+ 1));
1296 generating_code
= 0;
1299 handle_branch (&td
, MINT_BR_S
, MINT_BR
, 2 + (gint8
)td
.ip
[1]);
1301 generating_code
= 0;
1304 one_arg_branch (&td
, MINT_BRFALSE_I4
, 5 + read32 (td
.ip
+ 1));
1308 one_arg_branch (&td
, MINT_BRFALSE_I4
, 2 + (gint8
)td
.ip
[1]);
1312 one_arg_branch (&td
, MINT_BRTRUE_I4
, 5 + read32 (td
.ip
+ 1));
1316 one_arg_branch (&td
, MINT_BRTRUE_I4
, 2 + (gint8
)td
.ip
[1]);
1320 two_arg_branch (&td
, MINT_BEQ_I4
, 5 + read32 (td
.ip
+ 1));
1324 two_arg_branch (&td
, MINT_BEQ_I4
, 2 + (gint8
) td
.ip
[1]);
1328 two_arg_branch (&td
, MINT_BGE_I4
, 5 + read32 (td
.ip
+ 1));
1332 two_arg_branch (&td
, MINT_BGE_I4
, 2 + (gint8
) td
.ip
[1]);
1336 two_arg_branch (&td
, MINT_BGT_I4
, 5 + read32 (td
.ip
+ 1));
1340 two_arg_branch (&td
, MINT_BGT_I4
, 2 + (gint8
) td
.ip
[1]);
1344 two_arg_branch (&td
, MINT_BLT_I4
, 5 + read32 (td
.ip
+ 1));
1348 two_arg_branch (&td
, MINT_BLT_I4
, 2 + (gint8
) td
.ip
[1]);
1352 two_arg_branch (&td
, MINT_BLE_I4
, 5 + read32 (td
.ip
+ 1));
1356 two_arg_branch (&td
, MINT_BLE_I4
, 2 + (gint8
) td
.ip
[1]);
1360 two_arg_branch (&td
, MINT_BNE_UN_I4
, 5 + read32 (td
.ip
+ 1));
1364 two_arg_branch (&td
, MINT_BNE_UN_I4
, 2 + (gint8
) td
.ip
[1]);
1368 two_arg_branch (&td
, MINT_BGE_UN_I4
, 5 + read32 (td
.ip
+ 1));
1372 two_arg_branch (&td
, MINT_BGE_UN_I4
, 2 + (gint8
) td
.ip
[1]);
1376 two_arg_branch (&td
, MINT_BGT_UN_I4
, 5 + read32 (td
.ip
+ 1));
1380 two_arg_branch (&td
, MINT_BGT_UN_I4
, 2 + (gint8
) td
.ip
[1]);
1384 two_arg_branch (&td
, MINT_BLE_UN_I4
, 5 + read32 (td
.ip
+ 1));
1388 two_arg_branch (&td
, MINT_BLE_UN_I4
, 2 + (gint8
) td
.ip
[1]);
1392 two_arg_branch (&td
, MINT_BLT_UN_I4
, 5 + read32 (td
.ip
+ 1));
1396 two_arg_branch (&td
, MINT_BLT_UN_I4
, 2 + (gint8
) td
.ip
[1]);
1401 const unsigned char *next_ip
;
1402 const unsigned char *base_ip
= td
.ip
;
1403 unsigned short *next_new_ip
;
1406 ADD_CODE (&td
, MINT_SWITCH
);
1409 next_ip
= td
.ip
+ n
* 4;
1410 next_new_ip
= td
.new_ip
+ n
* 2;
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
;
1418 if (stack_height
> 0 && stack_height
!= td
.stack_height
[target
])
1419 g_warning ("SWITCH with back branch and non-empty stack");
1421 target
= td
.in_offsets
[target
] - (next_new_ip
- td
.new_code
);
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
);
1438 CHECK_STACK (&td
, 1);
1439 SIMPLE_OP (td
, MINT_LDIND_I1
);
1440 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1443 CHECK_STACK (&td
, 1);
1444 SIMPLE_OP (td
, MINT_LDIND_U1
);
1445 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1448 CHECK_STACK (&td
, 1);
1449 SIMPLE_OP (td
, MINT_LDIND_I2
);
1450 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1453 CHECK_STACK (&td
, 1);
1454 SIMPLE_OP (td
, MINT_LDIND_U2
);
1455 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1458 CHECK_STACK (&td
, 1);
1459 SIMPLE_OP (td
, MINT_LDIND_I4
);
1460 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1463 CHECK_STACK (&td
, 1);
1464 SIMPLE_OP (td
, MINT_LDIND_U4
);
1465 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1468 CHECK_STACK (&td
, 1);
1469 SIMPLE_OP (td
, MINT_LDIND_I8
);
1470 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
1473 CHECK_STACK (&td
, 1);
1474 SIMPLE_OP (td
, MINT_LDIND_I
);
1476 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I
);
1479 CHECK_STACK (&td
, 1);
1480 SIMPLE_OP (td
, MINT_LDIND_R4
);
1481 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
1484 CHECK_STACK (&td
, 1);
1485 SIMPLE_OP (td
, MINT_LDIND_R8
);
1486 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
1489 CHECK_STACK (&td
, 1);
1490 SIMPLE_OP (td
, MINT_LDIND_REF
);
1491 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_O
);
1494 CHECK_STACK (&td
, 2);
1495 SIMPLE_OP (td
, MINT_STIND_REF
);
1499 CHECK_STACK (&td
, 2);
1500 SIMPLE_OP (td
, MINT_STIND_I1
);
1504 CHECK_STACK (&td
, 2);
1505 SIMPLE_OP (td
, MINT_STIND_I2
);
1509 CHECK_STACK (&td
, 2);
1510 SIMPLE_OP (td
, MINT_STIND_I4
);
1514 CHECK_STACK (&td
, 2);
1515 SIMPLE_OP (td
, MINT_STIND_I
);
1519 CHECK_STACK (&td
, 2);
1520 SIMPLE_OP (td
, MINT_STIND_I8
);
1524 CHECK_STACK (&td
, 2);
1525 SIMPLE_OP (td
, MINT_STIND_R4
);
1529 CHECK_STACK (&td
, 2);
1530 SIMPLE_OP (td
, MINT_STIND_R8
);
1534 binary_arith_op(&td
, MINT_ADD_I4
);
1538 binary_arith_op(&td
, MINT_SUB_I4
);
1542 binary_arith_op(&td
, MINT_MUL_I4
);
1546 binary_arith_op(&td
, MINT_DIV_I4
);
1550 binary_arith_op(&td
, MINT_DIV_UN_I4
);
1554 binary_int_op (&td
, MINT_REM_I4
);
1558 binary_int_op (&td
, MINT_REM_UN_I4
);
1562 binary_int_op (&td
, MINT_AND_I4
);
1566 binary_int_op (&td
, MINT_OR_I4
);
1570 binary_int_op (&td
, MINT_XOR_I4
);
1574 shift_op (&td
, MINT_SHL_I4
);
1578 shift_op (&td
, MINT_SHR_I4
);
1582 shift_op (&td
, MINT_SHR_UN_I4
);
1586 unary_arith_op (&td
, MINT_NEG_I4
);
1590 unary_arith_op (&td
, MINT_NOT_I4
);
1594 CHECK_STACK (&td
, 1);
1595 switch (td
.sp
[-1].type
) {
1597 ADD_CODE(&td
, MINT_CONV_U1_R8
);
1600 ADD_CODE(&td
, MINT_CONV_U1_I4
);
1603 ADD_CODE(&td
, MINT_CONV_U1_I8
);
1606 g_assert_not_reached ();
1609 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1612 CHECK_STACK (&td
, 1);
1613 switch (td
.sp
[-1].type
) {
1615 ADD_CODE(&td
, MINT_CONV_I1_R8
);
1618 ADD_CODE(&td
, MINT_CONV_I1_I4
);
1621 ADD_CODE(&td
, MINT_CONV_I1_I8
);
1624 g_assert_not_reached ();
1627 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1630 CHECK_STACK (&td
, 1);
1631 switch (td
.sp
[-1].type
) {
1633 ADD_CODE(&td
, MINT_CONV_U2_R8
);
1636 ADD_CODE(&td
, MINT_CONV_U2_I4
);
1639 ADD_CODE(&td
, MINT_CONV_U2_I8
);
1642 g_assert_not_reached ();
1645 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1648 CHECK_STACK (&td
, 1);
1649 switch (td
.sp
[-1].type
) {
1651 ADD_CODE(&td
, MINT_CONV_I2_R8
);
1654 ADD_CODE(&td
, MINT_CONV_I2_I4
);
1657 ADD_CODE(&td
, MINT_CONV_I2_I8
);
1660 g_assert_not_reached ();
1663 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1666 CHECK_STACK (&td
, 1);
1667 switch (td
.sp
[-1].type
) {
1669 #if SIZEOF_VOID_P == 4
1670 ADD_CODE(&td
, MINT_CONV_U4_R8
);
1672 ADD_CODE(&td
, MINT_CONV_U8_R8
);
1676 #if SIZEOF_VOID_P == 8
1677 ADD_CODE(&td
, MINT_CONV_U8_I4
);
1681 #if SIZEOF_VOID_P == 4
1682 ADD_CODE(&td
, MINT_CONV_U4_I8
);
1688 g_assert_not_reached ();
1691 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I
);
1694 CHECK_STACK (&td
, 1);
1695 switch (td
.sp
[-1].type
) {
1697 #if SIZEOF_VOID_P == 8
1698 ADD_CODE(&td
, MINT_CONV_I8_R8
);
1700 ADD_CODE(&td
, MINT_CONV_I4_R8
);
1704 #if SIZEOF_VOID_P == 8
1705 ADD_CODE(&td
, MINT_CONV_I8_I4
);
1713 #if SIZEOF_VOID_P == 4
1714 ADD_CODE(&td
, MINT_CONV_I4_I8
);
1718 g_assert_not_reached ();
1721 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I
);
1724 CHECK_STACK (&td
, 1);
1725 switch (td
.sp
[-1].type
) {
1727 ADD_CODE(&td
, MINT_CONV_U4_R8
);
1732 ADD_CODE(&td
, MINT_CONV_U4_I8
);
1735 #if SIZEOF_VOID_P == 8
1736 ADD_CODE(&td
, MINT_CONV_U4_I8
);
1740 g_assert_not_reached ();
1743 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1746 CHECK_STACK (&td
, 1);
1747 switch (td
.sp
[-1].type
) {
1749 ADD_CODE(&td
, MINT_CONV_I4_R8
);
1754 ADD_CODE(&td
, MINT_CONV_I4_I8
);
1757 #if SIZEOF_VOID_P == 8
1758 ADD_CODE(&td
, MINT_CONV_I4_I8
);
1762 g_assert_not_reached ();
1765 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1768 CHECK_STACK (&td
, 1);
1769 switch (td
.sp
[-1].type
) {
1771 ADD_CODE(&td
, MINT_CONV_I8_R8
);
1774 ADD_CODE(&td
, MINT_CONV_I8_I4
);
1779 #if SIZEOF_VOID_P == 4
1780 ADD_CODE(&td
, MINT_CONV_I8_I4
);
1784 g_assert_not_reached ();
1787 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
1790 CHECK_STACK (&td
, 1);
1791 switch (td
.sp
[-1].type
) {
1793 ADD_CODE(&td
, MINT_CONV_R4_R8
);
1796 ADD_CODE(&td
, MINT_CONV_R4_I8
);
1799 ADD_CODE(&td
, MINT_CONV_R4_I4
);
1802 g_assert_not_reached ();
1805 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
1808 CHECK_STACK (&td
, 1);
1809 switch (td
.sp
[-1].type
) {
1811 ADD_CODE(&td
, MINT_CONV_R8_I4
);
1814 ADD_CODE(&td
, MINT_CONV_R8_I8
);
1819 g_assert_not_reached ();
1822 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
1825 CHECK_STACK (&td
, 1);
1826 switch (td
.sp
[-1].type
) {
1828 ADD_CODE(&td
, MINT_CONV_U8_I4
);
1833 ADD_CODE(&td
, MINT_CONV_U8_R8
);
1836 #if SIZEOF_VOID_P == 4
1837 ADD_CODE(&td
, MINT_CONV_U8_I4
);
1841 g_assert_not_reached ();
1844 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
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
));
1856 ADD_CODE (&td
, MINT_LDIND_REF
);
1857 ADD_CODE (&td
, MINT_STIND_REF
);
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
);
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
);
1881 SET_TYPE(td
.sp
- 1, stack_type
[mint_type(&klass
->byval_arg
)], klass
);
1886 token
= mono_metadata_token_index (read32 (td
.ip
+ 1));
1888 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
) {
1889 s
= mono_string_new_wrapper(
1890 mono_method_get_wrapper_data (method
, token
));
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
);
1901 MonoMethodSignature
*csignature
;
1902 guint32 vt_stack_used
= 0;
1903 guint32 vt_res_size
= 0;
1906 token
= read32 (td
.ip
);
1909 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
1910 m
= (MonoMethod
*)mono_method_get_wrapper_data (method
, token
);
1912 m
= mono_get_method_full (image
, token
, NULL
, generic_context
);
1914 csignature
= mono_method_signature (m
);
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
);
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
;
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
));
1961 switch (td
.sp
[-1].type
) {
1965 ADD_CODE(&td
, MINT_CONV_R_UN_I8
);
1968 ADD_CODE(&td
, MINT_CONV_R_UN_I4
);
1971 g_assert_not_reached ();
1973 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
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
);
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
);
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
);
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
);
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
);
2028 CHECK_STACK (&td
, 1);
2029 SIMPLE_OP (td
, MINT_THROW
);
2031 generating_code
= 0;
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
);
2040 ADD_CODE (&td
, MINT_POP
);
2042 ADD_CODE (&td
, MINT_LDSFLDA
);
2043 ADD_CODE (&td
, get_data_item_index (&td
, field
));
2045 if ((td
.sp
- 1)->type
== STACK_TYPE_O
) {
2046 ADD_CODE (&td
, MINT_LDFLDA
);
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
);
2054 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_MP
);
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
));
2071 ADD_CODE (&td
, MINT_POP
);
2073 ADD_CODE (&td
, mt
== MINT_TYPE_VT
? MINT_LDSFLD_VT
: MINT_LDSFLD
);
2074 ADD_CODE (&td
, get_data_item_index (&td
, field
));
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
);
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;
2089 ADD_CODE (&td
, MINT_VTRESULT
);
2091 WRITE32 (&td
, &size
);
2094 SET_TYPE(td
.sp
- 1, stack_type
[mt
], field_klass
);
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
));
2111 ADD_CODE (&td
, MINT_POP
);
2113 ADD_CODE (&td
, mt
== MINT_TYPE_VT
? MINT_STSFLD_VT
: MINT_STSFLD
);
2114 ADD_CODE (&td
, get_data_item_index (&td
, field
));
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
);
2124 WRITE32(&td
, &size
);
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
));
2136 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_MP
);
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
));
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
);
2149 WRITE32(&td
, &size
);
2150 klass
= field
->type
->data
.klass
;
2152 if (mt
== MINT_TYPE_O
)
2153 klass
= mono_class_from_mono_type (field
->type
);
2156 PUSH_TYPE(&td
, stack_type
[mt
], klass
);
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
);
2169 WRITE32 (&td
, &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
);
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;
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
) {
2199 #if SIZEOF_VOID_P == 8
2200 ADD_CODE(&td
, MINT_CONV_OVF_I8_UN_R8
);
2202 ADD_CODE(&td
, MINT_CONV_OVF_I4_UN_R8
);
2206 #if SIZEOF_VOID_P == 4
2207 ADD_CODE (&td
, MINT_CONV_OVF_I4_UN_I8
);
2211 #if SIZEOF_VOID_P == 8
2212 ADD_CODE(&td
, MINT_CONV_I8_U4
);
2216 g_assert_not_reached ();
2219 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
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
) {
2227 ADD_CODE(&td
, MINT_CONV_OVF_I8_UN_R8
);
2230 if (*td
.ip
== CEE_CONV_OVF_I8_UN
)
2231 ADD_CODE (&td
, MINT_CONV_OVF_I8_U8
);
2234 ADD_CODE(&td
, MINT_CONV_I8_U4
);
2237 g_assert_not_reached ();
2240 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
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
);
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. */
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;
2265 ADD_CODE(&td
, MINT_BOX
);
2266 ADD_CODE(&td
, get_data_item_index (&td
, klass
));
2268 SET_TYPE(td
.sp
- 1, STACK_TYPE_O
, klass
);
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
);
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
);
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
);
2299 CHECK_STACK (&td
, 1);
2300 SIMPLE_OP (td
, MINT_LDLEN
);
2301 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I
);
2304 CHECK_STACK (&td
, 2);
2306 token
= read32 (td
.ip
+ 1);
2308 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
2309 klass
= (MonoClass
*) mono_method_get_wrapper_data (method
, token
);
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
);
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 */
2325 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_MP
);
2328 CHECK_STACK (&td
, 2);
2330 SIMPLE_OP (td
, MINT_LDELEM_I1
);
2332 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2335 CHECK_STACK (&td
, 2);
2337 SIMPLE_OP (td
, MINT_LDELEM_U1
);
2339 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2342 CHECK_STACK (&td
, 2);
2344 SIMPLE_OP (td
, MINT_LDELEM_I2
);
2346 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2349 CHECK_STACK (&td
, 2);
2351 SIMPLE_OP (td
, MINT_LDELEM_U2
);
2353 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2356 CHECK_STACK (&td
, 2);
2358 SIMPLE_OP (td
, MINT_LDELEM_I4
);
2360 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2363 CHECK_STACK (&td
, 2);
2365 SIMPLE_OP (td
, MINT_LDELEM_U4
);
2367 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2370 CHECK_STACK (&td
, 2);
2372 SIMPLE_OP (td
, MINT_LDELEM_I8
);
2374 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
2377 CHECK_STACK (&td
, 2);
2379 SIMPLE_OP (td
, MINT_LDELEM_I
);
2381 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I
);
2384 CHECK_STACK (&td
, 2);
2386 SIMPLE_OP (td
, MINT_LDELEM_R4
);
2388 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
2391 CHECK_STACK (&td
, 2);
2393 SIMPLE_OP (td
, MINT_LDELEM_R8
);
2395 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
2397 case CEE_LDELEM_REF
:
2398 CHECK_STACK (&td
, 2);
2400 SIMPLE_OP (td
, MINT_LDELEM_REF
);
2402 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_O
);
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
)) {
2411 SIMPLE_OP (td
, MINT_LDELEM_I1
);
2413 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2417 SIMPLE_OP (td
, MINT_LDELEM_U1
);
2419 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2423 SIMPLE_OP (td
, MINT_LDELEM_U2
);
2425 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2429 SIMPLE_OP (td
, MINT_LDELEM_I2
);
2431 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2435 SIMPLE_OP (td
, MINT_LDELEM_I4
);
2437 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2441 SIMPLE_OP (td
, MINT_LDELEM_I8
);
2443 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
2447 SIMPLE_OP (td
, MINT_LDELEM_R4
);
2449 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
2453 SIMPLE_OP (td
, MINT_LDELEM_R8
);
2455 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
2459 SIMPLE_OP (td
, MINT_LDELEM_REF
);
2461 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_O
);
2463 case MINT_TYPE_VT
: {
2464 int size
= mono_class_value_size (klass
, NULL
);
2466 SIMPLE_OP (td
, MINT_LDELEM_VT
);
2467 ADD_CODE (&td
, get_data_item_index (&td
, klass
));
2468 WRITE32 (&td
, &size
);
2470 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_VT
);
2471 PUSH_VT (&td
, size
);
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
);
2486 CHECK_STACK (&td
, 3);
2488 SIMPLE_OP (td
, MINT_STELEM_I
);
2492 CHECK_STACK (&td
, 3);
2494 SIMPLE_OP (td
, MINT_STELEM_I1
);
2498 CHECK_STACK (&td
, 3);
2500 SIMPLE_OP (td
, MINT_STELEM_I2
);
2504 CHECK_STACK (&td
, 3);
2506 SIMPLE_OP (td
, MINT_STELEM_I4
);
2510 CHECK_STACK (&td
, 3);
2512 SIMPLE_OP (td
, MINT_STELEM_I8
);
2516 CHECK_STACK (&td
, 3);
2518 SIMPLE_OP (td
, MINT_STELEM_R4
);
2522 CHECK_STACK (&td
, 3);
2524 SIMPLE_OP (td
, MINT_STELEM_R8
);
2527 case CEE_STELEM_REF
:
2528 CHECK_STACK (&td
, 3);
2530 SIMPLE_OP (td
, MINT_STELEM_REF
);
2534 CHECK_STACK (&td
, 3);
2536 token
= read32 (td
.ip
+ 1);
2537 klass
= mono_class_get_full (image
, token
, generic_context
);
2538 switch (mint_type (&klass
->byval_arg
)) {
2540 SIMPLE_OP (td
, MINT_STELEM_U1
);
2543 SIMPLE_OP (td
, MINT_STELEM_U2
);
2546 SIMPLE_OP (td
, MINT_STELEM_I4
);
2549 SIMPLE_OP (td
, MINT_STELEM_I8
);
2552 SIMPLE_OP (td
, MINT_STELEM_REF
);
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
);
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
);
2575 case CEE_CONV_OVF_U1
:
2577 case CEE_CONV_OVF_I8
:
2579 #if SIZEOF_VOID_P == 8
2580 case CEE_CONV_OVF_U
:
2582 case CEE_REFANYVAL
: ves_abort(); break;
2585 CHECK_STACK (&td
, 1);
2586 SIMPLE_OP (td
, MINT_CKFINITE
);
2588 case CEE_CONV_OVF_I1
:
2589 case CEE_CONV_OVF_I1_UN
:
2590 CHECK_STACK (&td
, 1);
2591 switch (td
.sp
[-1].type
) {
2593 ADD_CODE(&td
, MINT_CONV_OVF_I1_R8
);
2596 ADD_CODE(&td
, MINT_CONV_OVF_I1_I4
);
2599 ADD_CODE(&td
, MINT_CONV_OVF_I1_I8
);
2602 g_assert_not_reached ();
2605 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2607 case CEE_CONV_OVF_U1
:
2608 case CEE_CONV_OVF_U1_UN
:
2609 CHECK_STACK (&td
, 1);
2610 switch (td
.sp
[-1].type
) {
2612 ADD_CODE(&td
, MINT_CONV_OVF_U1_R8
);
2615 ADD_CODE(&td
, MINT_CONV_OVF_U1_I4
);
2618 ADD_CODE(&td
, MINT_CONV_OVF_U1_I8
);
2621 g_assert_not_reached ();
2624 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2626 case CEE_CONV_OVF_I2
:
2627 case CEE_CONV_OVF_I2_UN
:
2628 CHECK_STACK (&td
, 1);
2629 switch (td
.sp
[-1].type
) {
2631 ADD_CODE(&td
, MINT_CONV_OVF_I2_R8
);
2634 ADD_CODE(&td
, MINT_CONV_OVF_I2_I4
);
2637 ADD_CODE(&td
, MINT_CONV_OVF_I2_I8
);
2640 g_assert_not_reached ();
2643 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2645 case CEE_CONV_OVF_U2_UN
:
2646 case CEE_CONV_OVF_U2
:
2647 CHECK_STACK (&td
, 1);
2648 switch (td
.sp
[-1].type
) {
2650 ADD_CODE(&td
, MINT_CONV_OVF_U2_R8
);
2653 ADD_CODE(&td
, MINT_CONV_OVF_U2_I4
);
2656 ADD_CODE(&td
, MINT_CONV_OVF_U2_I8
);
2659 g_assert_not_reached ();
2662 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2664 #if SIZEOF_VOID_P == 4
2665 case CEE_CONV_OVF_I
:
2667 case CEE_CONV_OVF_I4
:
2668 case CEE_CONV_OVF_I4_UN
:
2669 CHECK_STACK (&td
, 1);
2670 switch (td
.sp
[-1].type
) {
2672 ADD_CODE(&td
, MINT_CONV_OVF_I4_R8
);
2675 if (*td
.ip
== CEE_CONV_OVF_I4_UN
)
2676 ADD_CODE(&td
, MINT_CONV_OVF_I4_U4
);
2679 if (*td
.ip
== CEE_CONV_OVF_I4_UN
)
2680 ADD_CODE (&td
, MINT_CONV_OVF_I4_U8
);
2682 ADD_CODE (&td
, MINT_CONV_OVF_I4_I8
);
2685 g_assert_not_reached ();
2688 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2690 #if SIZEOF_VOID_P == 4
2691 case CEE_CONV_OVF_U
:
2693 case CEE_CONV_OVF_U4
:
2694 case CEE_CONV_OVF_U4_UN
:
2695 CHECK_STACK (&td
, 1);
2696 switch (td
.sp
[-1].type
) {
2698 ADD_CODE(&td
, MINT_CONV_OVF_U4_R8
);
2701 if (*td
.ip
!= CEE_CONV_OVF_U4_UN
)
2702 ADD_CODE(&td
, MINT_CONV_OVF_U4_I4
);
2705 ADD_CODE(&td
, MINT_CONV_OVF_U4_I8
);
2708 g_assert_not_reached ();
2711 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2713 #if SIZEOF_VOID_P == 8
2714 case CEE_CONV_OVF_I
:
2716 case CEE_CONV_OVF_I8
:
2717 CHECK_STACK (&td
, 1);
2718 switch (td
.sp
[-1].type
) {
2720 ADD_CODE(&td
, MINT_CONV_OVF_I8_R8
);
2723 ADD_CODE(&td
, MINT_CONV_I8_I4
);
2728 g_assert_not_reached ();
2731 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
2733 #if SIZEOF_VOID_P == 8
2734 case CEE_CONV_OVF_U
:
2736 case CEE_CONV_OVF_U8
:
2737 CHECK_STACK (&td
, 1);
2738 switch (td
.sp
[-1].type
) {
2740 ADD_CODE(&td
, MINT_CONV_OVF_U8_R8
);
2743 ADD_CODE(&td
, MINT_CONV_OVF_U8_I4
);
2746 ADD_CODE (&td
, MINT_CONV_OVF_U8_I8
);
2749 g_assert_not_reached ();
2752 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
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 */
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
);
2786 binary_arith_op(&td
, MINT_ADD_OVF_I4
);
2789 case CEE_ADD_OVF_UN
:
2790 binary_arith_op(&td
, MINT_ADD_OVF_UN_I4
);
2794 binary_arith_op(&td
, MINT_MUL_OVF_I4
);
2797 case CEE_MUL_OVF_UN
:
2798 binary_arith_op(&td
, MINT_MUL_OVF_UN_I4
);
2802 binary_arith_op(&td
, MINT_SUB_OVF_I4
);
2805 case CEE_SUB_OVF_UN
:
2806 binary_arith_op(&td
, MINT_SUB_OVF_UN_I4
);
2809 case CEE_ENDFINALLY
:
2811 SIMPLE_OP (td
, MINT_ENDFINALLY
);
2812 generating_code
= 0;
2816 handle_branch (&td
, MINT_LEAVE_S
, MINT_LEAVE
, 5 + read32 (td
.ip
+ 1));
2818 generating_code
= 0;
2822 handle_branch (&td
, MINT_LEAVE_S
, MINT_LEAVE
, 2 + (gint8
)td
.ip
[1]);
2824 generating_code
= 0;
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
);
2834 interp_transform_call (&td
, method
, NULL
, domain
, generic_context
, is_bb_start
, body_start_offset
, NULL
, FALSE
);
2836 case CEE_MONO_JIT_ICALL_ADDR
: {
2839 MonoJitICallInfo
*info
;
2841 token
= read32 (td
.ip
+ 1);
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
);
2851 case CEE_MONO_ICALL
: {
2854 MonoJitICallInfo
*info
;
2856 token
= read32 (td
.ip
+ 1);
2858 func
= mono_method_get_wrapper_data (method
, token
);
2859 info
= mono_find_jit_icall_by_addr (func
);
2862 CHECK_STACK (&td
, info
->sig
->param_count
);
2863 switch (info
->sig
->param_count
) {
2865 if (MONO_TYPE_IS_VOID (info
->sig
->ret
))
2866 ADD_CODE (&td
,MINT_ICALL_V_V
);
2868 ADD_CODE (&td
, MINT_ICALL_V_P
);
2871 if (MONO_TYPE_IS_VOID (info
->sig
->ret
))
2872 ADD_CODE (&td
,MINT_ICALL_P_V
);
2874 ADD_CODE (&td
,MINT_ICALL_P_P
);
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
);
2881 ADD_CODE (&td
,MINT_ICALL_PP_V
);
2883 if (info
->sig
->params
[1]->type
== MONO_TYPE_I4
)
2884 ADD_CODE (&td
,MINT_ICALL_PI_P
);
2886 ADD_CODE (&td
,MINT_ICALL_PP_P
);
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
);
2894 ADD_CODE (&td
,MINT_ICALL_PPP_V
);
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
)) {
2908 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I
);
2912 case CEE_MONO_VTADDR
: {
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
);
2918 size
= mono_class_value_size(td
.sp
[-1].klass
, NULL
);
2919 size
= (size
+ 7) & ~7;
2920 ADD_CODE(&td
, MINT_VTRESULT
);
2922 WRITE32(&td
, &size
);
2925 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_MP
);
2928 case CEE_MONO_LDPTR
:
2929 case CEE_MONO_CLASSCONST
:
2930 token
= read32 (td
.ip
+ 1);
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
;
2937 case CEE_MONO_OBJADDR
:
2938 CHECK_STACK (&td
, 1);
2940 td
.sp
[-1].type
= STACK_TYPE_MP
;
2943 case CEE_MONO_NEWOBJ
:
2944 token
= read32 (td
.ip
+ 1);
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
;
2951 case CEE_MONO_RETOBJ
:
2952 CHECK_STACK (&td
, 1);
2953 token
= read32 (td
.ip
+ 1);
2955 ADD_CODE(&td
, MINT_MONO_RETOBJ
);
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
);
2965 case CEE_MONO_LDNATIVEOBJ
:
2966 token
= read32 (td
.ip
+ 1);
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
);
2972 case CEE_MONO_SAVE_LMF
:
2973 case CEE_MONO_RESTORE_LMF
:
2974 case CEE_MONO_NOT_TAKEN
:
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
);
2984 g_error ("transform.c: Unimplemented opcode: 0xF0 %02x at 0x%x\n", *td
.ip
, td
.ip
-header
->code
);
2994 case CEE_PREFIXREF
: ves_abort(); break;
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).
3005 case CEE_ARGLIST
: ves_abort(); break;
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
);
3012 ADD_CODE(&td
, MINT_CEQ_I4
+ td
.sp
[-1].type
- STACK_TYPE_I4
);
3014 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
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
);
3022 ADD_CODE(&td
, MINT_CGT_I4
+ td
.sp
[-1].type
- STACK_TYPE_I4
);
3024 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
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
);
3032 ADD_CODE(&td
, MINT_CGT_UN_I4
+ td
.sp
[-1].type
- STACK_TYPE_I4
);
3034 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
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
);
3042 ADD_CODE(&td
, MINT_CLT_I4
+ td
.sp
[-1].type
- STACK_TYPE_I4
);
3044 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
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
);
3052 ADD_CODE(&td
, MINT_CLT_UN_I4
+ td
.sp
[-1].type
- STACK_TYPE_I4
);
3054 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
3057 case CEE_LDVIRTFTN
: /* fallthrough */
3060 if (*td
.ip
== CEE_LDVIRTFTN
) {
3061 CHECK_STACK (&td
, 1);
3064 token
= read32 (td
.ip
+ 1);
3065 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
3066 m
= (MonoMethod
*)mono_method_get_wrapper_data (method
, token
);
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 */
3077 PUSH_SIMPLE_TYPE (&td
, STACK_TYPE_F
);
3081 load_arg (&td
, read16 (td
.ip
+ 1));
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
);
3093 store_arg (&td
, read16 (td
.ip
+ 1));
3097 load_local (&td
, read16 (td
.ip
+ 1));
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
);
3107 store_local (&td
, read16 (td
.ip
+ 1));
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
);
3116 ADD_CODE(&td
, MINT_LOCALLOC
);
3117 if (td
.sp
!= td
.stack
+ 1)
3118 g_warning("CEE_LOCALLOC: stack not empty");
3120 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_MP
);
3123 case CEE_UNUSED57
: ves_abort(); break;
3126 ADD_CODE (&td
, MINT_ENDFILTER
);
3129 case CEE_UNALIGNED_
:
3131 /* FIX: should do something? */;
3135 /* FIX: should do something? */;
3139 /* FIX: should do something? */;
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
);
3150 ADD_CODE (&td
, MINT_LDNULL
);
3151 ADD_CODE (&td
, MINT_STIND_REF
);
3157 CHECK_STACK(&td
, 3);
3158 /* FIX? convert length to I8? */
3159 ADD_CODE(&td
, MINT_CPBLK
);
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
);
3174 CHECK_STACK(&td
, 3);
3175 ADD_CODE(&td
, MINT_INITBLK
);
3181 /* FIXME: implement */
3186 SIMPLE_OP (td
, MINT_RETHROW
);
3187 generating_code
= 0;
3191 token
= read32 (td
.ip
+ 1);
3193 if (mono_metadata_token_table (token
) == MONO_TABLE_TYPESPEC
&& !image_is_dynamic (method
->klass
->image
) && !generic_context
) {
3195 MonoType
*type
= mono_type_create_from_typespec (image
, token
);
3196 size
= mono_type_size (type
, &align
);
3199 MonoClass
*szclass
= mono_class_get_full (image
, token
, generic_context
);
3200 mono_class_init (szclass
);
3202 if (!szclass
->valuetype
)
3203 THROW_EX (mono_exception_from_name (mono_defaults
.corlib
, "System", "InvalidProgramException"), ip
- 5);
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
);
3213 case CEE_REFANYTYPE
: ves_abort(); break;
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
);
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
);
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
);
3273 g_hash_table_destroy (td
.data_hash
);
3276 static mono_mutex_t calc_section
;
3279 mono_interp_transform_init (void)
3281 mono_os_mutex_init_recursive(&calc_section
);
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
;
3296 MonoDomain
*domain
= mono_domain_get ();
3297 unsigned char *is_bb_start
;
3299 MonoVTable
*method_class_vt
;
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
) {
3308 MonoInvocation
*last_env_frame
= context
->env_frame
;
3309 jmp_buf *old_env
= context
->current_env
;
3310 error_init (&error
);
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
;
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
);
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
);
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
);
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");
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
);
3369 runtime_method
->code
= g_malloc(sizeof(short));
3370 runtime_method
->code
[0] = MINT_CALLRUN
;
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
);
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
);
3397 } else if (!strcmp (method
->name
, "UnsafeStore)")) {
3399 } else if (!strcmp (method
->name
, "UnsafeLoad)")) {
3403 g_assert ((signature
->param_count
+ signature
->hasthis
) < 1000);
3404 g_assert (header
->max_stack
< 10000);
3405 /* intern the strings in the method. */
3407 end
= ip
+ header
->code_size
;
3409 is_bb_start
= g_malloc0(header
->code_size
);
3410 is_bb_start
[0] = 1;
3417 else if (in
== 0xf0) {
3419 in
= *ip
+ MONO_CEE_MONO_ICALL
;
3421 opcode
= &mono_opcodes
[in
];
3422 switch (opcode
->argument
) {
3423 case MonoInlineNone
:
3426 case MonoInlineString
:
3427 if (method
->wrapper_type
== MONO_WRAPPER_NONE
)
3428 mono_ldstr (domain
, image
, mono_metadata_token_index (read32 (ip
+ 1)));
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 */
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);
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
);
3448 g_free (is_bb_start
);
3449 g_error ("FIXME: where to get method and class string?");
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
);
3459 case MonoInlineField
:
3463 case MonoShortInlineR
:
3466 case MonoInlineBrTarget
:
3467 offset
= read32 (ip
+ 1);
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;
3474 case MonoShortInlineBrTarget
:
3475 offset
= ((gint8
*)ip
) [1];
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;
3485 case MonoShortInlineVar
:
3486 case MonoShortInlineI
:
3489 case MonoInlineSwitch
: {
3491 const unsigned char *next_ip
;
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;
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
);
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;
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
;
3536 offset
= (offset
+ 7) & ~7;
3537 runtime_method
->locals_size
= offset
;
3538 g_assert (runtime_method
->locals_size
< 65536);
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
;
3551 for (i
= 0; i
< signature
->param_count
; ++i
) {
3552 if (signature
->pinvoke
) {
3554 size
= mono_type_native_stack_size (signature
->params
[i
], &dummy
);
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
;
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
);