2 * transform CIL into different opcodes for more
3 * efficient interpretation
5 * Written by Bernie Solomon (bernard@ugsolutions.com)
10 #include <mono/metadata/appdomain.h>
11 #include <mono/metadata/debug-helpers.h>
12 #include <mono/metadata/exception.h>
13 #include <mono/metadata/mono-endian.h>
14 #include <mono/metadata/marshal.h>
15 #include <mono/metadata/profiler-private.h>
16 #include <mono/metadata/tabledefs.h>
18 #include <mono/mini/mini.h>
21 #include "interp-internals.h"
24 // TODO: export from marshal.c
25 MonoDelegate
* mono_ftnptr_to_delegate (MonoClass
*klass
, gpointer ftn
);
39 MonoMethodHeader
*header
;
41 const unsigned char *il_code
;
42 const unsigned char *ip
;
43 const unsigned char *last_ip
;
44 const unsigned char *in_start
;
48 StackInfo
**stack_state
;
51 unsigned char *is_bb_start
;
52 unsigned short *new_code
;
53 unsigned short *new_code_end
;
54 unsigned short *new_ip
;
55 unsigned short *last_new_ip
;
56 unsigned int max_code_size
;
59 unsigned int max_stack_height
;
61 unsigned int max_vt_sp
;
65 GHashTable
*data_hash
;
68 #define MINT_TYPE_I1 0
69 #define MINT_TYPE_U1 1
70 #define MINT_TYPE_I2 2
71 #define MINT_TYPE_U2 3
72 #define MINT_TYPE_I4 4
73 #define MINT_TYPE_I8 5
74 #define MINT_TYPE_R4 6
75 #define MINT_TYPE_R8 7
78 #define MINT_TYPE_VT 10
80 #define STACK_TYPE_I4 0
81 #define STACK_TYPE_I8 1
82 #define STACK_TYPE_R8 2
83 #define STACK_TYPE_O 3
84 #define STACK_TYPE_VT 4
85 #define STACK_TYPE_MP 5
86 #define STACK_TYPE_F 6
88 static const char *stack_type_string
[] = { "I4", "I8", "R8", "O ", "VT", "MP", "F " };
90 #if SIZEOF_VOID_P == 8
91 #define STACK_TYPE_I STACK_TYPE_I8
93 #define STACK_TYPE_I STACK_TYPE_I4
96 static int stack_type
[] = {
100 STACK_TYPE_I4
, /*U2*/
101 STACK_TYPE_I4
, /*I4*/
102 STACK_TYPE_I8
, /*I8*/
103 STACK_TYPE_R8
, /*R4*/
104 STACK_TYPE_R8
, /*R8*/
111 grow_code (TransformData
*td
)
113 unsigned int old_ip_offset
= td
->new_ip
- td
->new_code
;
114 unsigned int old_last_ip_offset
= td
->last_new_ip
- td
->new_code
;
115 g_assert (old_ip_offset
<= td
->max_code_size
);
116 td
->new_code
= g_realloc (td
->new_code
, (td
->max_code_size
*= 2) * sizeof (td
->new_code
[0]));
117 td
->new_code_end
= td
->new_code
+ td
->max_code_size
;
118 td
->new_ip
= td
->new_code
+ old_ip_offset
;
119 td
->last_new_ip
= td
->new_code
+ old_last_ip_offset
;
122 #define ENSURE_CODE(td, n) \
124 if ((td)->new_ip + (n) > (td)->new_code_end) \
128 #define ADD_CODE(td, n) \
130 if ((td)->new_ip == (td)->new_code_end) \
132 *(td)->new_ip++ = (n); \
135 #define CHECK_STACK(td, n) \
137 int stack_size = (td)->sp - (td)->stack; \
138 if (stack_size < (n)) \
139 g_warning ("%s.%s: not enough values (%d < %d) on stack at %04x", \
140 (td)->method->klass->name, (td)->method->name, \
141 stack_size, n, (td)->ip - (td)->il_code); \
144 #define ENSURE_I4(td, sp_off) \
146 if ((td)->sp [-sp_off].type == STACK_TYPE_I8) \
147 ADD_CODE(td, sp_off == 1 ? MINT_CONV_I4_I8 : MINT_CONV_I4_I8_SP); \
151 handle_branch(TransformData
*td
, int short_op
, int long_op
, int offset
)
153 int shorten_branch
= 0;
154 int target
= td
->ip
+ offset
- td
->il_code
;
155 if (target
< 0 || target
>= td
->code_size
)
156 g_assert_not_reached ();
157 if (offset
> 0 && td
->stack_height
[target
] < 0) {
158 td
->stack_height
[target
] = td
->sp
- td
->stack
;
159 if (td
->stack_height
[target
] > 0)
160 td
->stack_state
[target
] = g_memdup (td
->stack
, td
->stack_height
[target
] * sizeof (td
->stack
[0]));
161 td
->vt_stack_size
[target
] = td
->vt_sp
;
164 offset
= td
->in_offsets
[target
] - (td
->new_ip
- td
->new_code
);
165 if (offset
>= -32768) {
169 int prev
= td
->forward_refs
[target
];
170 td
->forward_refs
[td
->ip
- td
->il_code
] = prev
;
171 td
->forward_refs
[target
] = td
->ip
- td
->il_code
;
173 if (td
->header
->code_size
<= 25000) /* FIX to be precise somehow? */
176 if (shorten_branch
) {
177 ADD_CODE(td
, short_op
);
178 ADD_CODE(td
, offset
);
180 ADD_CODE(td
, long_op
);
181 ADD_CODE(td
, * (unsigned short *)(&offset
));
182 ADD_CODE(td
, * ((unsigned short *)&offset
+ 1));
187 one_arg_branch(TransformData
*td
, int mint_op
, int offset
)
189 int type
= td
->sp
[-1].type
== STACK_TYPE_O
|| td
->sp
[-1].type
== STACK_TYPE_MP
? STACK_TYPE_I
: td
->sp
[-1].type
;
190 int long_op
= mint_op
+ type
- STACK_TYPE_I4
;
191 int short_op
= long_op
+ MINT_BRFALSE_I4_S
- MINT_BRFALSE_I4
;
194 handle_branch (td
, short_op
, long_op
, offset
);
198 two_arg_branch(TransformData
*td
, int mint_op
, int offset
)
200 int type1
= td
->sp
[-1].type
== STACK_TYPE_O
|| td
->sp
[-1].type
== STACK_TYPE_MP
? STACK_TYPE_I
: td
->sp
[-1].type
;
201 int type2
= td
->sp
[-2].type
== STACK_TYPE_O
|| td
->sp
[-2].type
== STACK_TYPE_MP
? STACK_TYPE_I
: td
->sp
[-2].type
;
202 int long_op
= mint_op
+ type1
- STACK_TYPE_I4
;
203 int short_op
= long_op
+ MINT_BEQ_I4_S
- MINT_BEQ_I4
;
205 if (type1
== STACK_TYPE_I4
&& type2
== STACK_TYPE_I8
) {
206 ADD_CODE(td
, MINT_CONV_I8_I4
);
207 td
->in_offsets
[td
->ip
- td
->il_code
]++;
208 } else if (type1
== STACK_TYPE_I8
&& type2
== STACK_TYPE_I4
) {
209 ADD_CODE(td
, MINT_CONV_I8_I4_SP
);
210 td
->in_offsets
[td
->ip
- td
->il_code
]++;
211 } else if (type1
!= type2
) {
212 g_warning("%s.%s: branch type mismatch %d %d",
213 td
->method
->klass
->name
, td
->method
->name
,
214 td
->sp
[-1].type
, td
->sp
[-2].type
);
217 handle_branch (td
, short_op
, long_op
, offset
);
221 unary_arith_op(TransformData
*td
, int mint_op
)
223 int op
= mint_op
+ td
->sp
[-1].type
- STACK_TYPE_I4
;
229 binary_arith_op(TransformData
*td
, int mint_op
)
231 int type1
= td
->sp
[-2].type
;
232 int type2
= td
->sp
[-1].type
;
234 #if SIZEOF_VOID_P == 8
235 if ((type1
== STACK_TYPE_MP
|| type1
== STACK_TYPE_I8
) && type2
== STACK_TYPE_I4
) {
236 ADD_CODE(td
, MINT_CONV_I8_I4
);
237 type2
= STACK_TYPE_I8
;
239 if (type1
== STACK_TYPE_I4
&& (type2
== STACK_TYPE_MP
|| type2
== STACK_TYPE_I8
)) {
240 ADD_CODE(td
, MINT_CONV_I8_I4_SP
);
241 type1
= STACK_TYPE_I8
;
242 td
->sp
[-2].type
= STACK_TYPE_I8
;
245 if (type1
== STACK_TYPE_MP
)
246 type1
= STACK_TYPE_I
;
247 if (type2
== STACK_TYPE_MP
)
248 type2
= STACK_TYPE_I
;
249 if (type1
!= type2
) {
250 g_warning("%s.%s: %04x arith type mismatch %s %d %d",
251 td
->method
->klass
->name
, td
->method
->name
,
252 td
->ip
- td
->il_code
, mono_interp_opname
[mint_op
], type1
, type2
);
254 op
= mint_op
+ type1
- STACK_TYPE_I4
;
261 binary_int_op(TransformData
*td
, int mint_op
)
263 int op
= mint_op
+ td
->sp
[-1].type
- STACK_TYPE_I4
;
265 if (td
->sp
[-1].type
!= td
->sp
[-2].type
)
266 g_warning("%s.%s: int type mismatch", td
->method
->klass
->name
, td
->method
->name
);
272 shift_op(TransformData
*td
, int mint_op
)
274 int op
= mint_op
+ td
->sp
[-2].type
- STACK_TYPE_I4
;
276 if (td
->sp
[-1].type
!= STACK_TYPE_I4
) {
277 g_warning("%s.%s: shift type mismatch %d",
278 td
->method
->klass
->name
, td
->method
->name
,
286 mint_type(MonoType
*type
)
291 switch (type
->type
) {
295 case MONO_TYPE_BOOLEAN
:
307 #if SIZEOF_VOID_P == 4
321 case MONO_TYPE_STRING
:
322 case MONO_TYPE_SZARRAY
:
323 case MONO_TYPE_CLASS
:
324 case MONO_TYPE_OBJECT
:
325 case MONO_TYPE_ARRAY
:
327 case MONO_TYPE_VALUETYPE
:
328 if (type
->data
.klass
->enumtype
) {
329 type
= mono_class_enum_basetype (type
->data
.klass
);
333 case MONO_TYPE_GENERICINST
:
334 type
= &type
->data
.generic_class
->container_class
->byval_arg
;
337 g_warning ("got type 0x%02x", type
->type
);
338 g_assert_not_reached ();
344 can_store (int stack_type
, int var_type
)
346 if (stack_type
== STACK_TYPE_O
|| stack_type
== STACK_TYPE_MP
)
347 stack_type
= STACK_TYPE_I
;
348 if (var_type
== STACK_TYPE_O
|| var_type
== STACK_TYPE_MP
)
349 var_type
= STACK_TYPE_I
;
350 return stack_type
== var_type
;
353 #define SET_SIMPLE_TYPE(s, ty) \
360 #define SET_TYPE(s, ty, k) \
367 #define PUSH_SIMPLE_TYPE(td, ty) \
371 sp_height = (td)->sp - (td)->stack; \
372 if (sp_height > (td)->max_stack_height) \
373 (td)->max_stack_height = sp_height; \
374 SET_SIMPLE_TYPE((td)->sp - 1, ty); \
377 #define PUSH_TYPE(td, ty, k) \
381 sp_height = (td)->sp - (td)->stack; \
382 if (sp_height > (td)->max_stack_height) \
383 (td)->max_stack_height = sp_height; \
384 SET_TYPE((td)->sp - 1, ty, k); \
387 #define PUSH_VT(td, size) \
389 (td)->vt_sp += ((size) + 7) & ~7; \
390 if ((td)->vt_sp > (td)->max_vt_sp) \
391 (td)->max_vt_sp = (td)->vt_sp; \
394 #define POP_VT(td, size) \
396 (td)->vt_sp -= ((size) + 7) & ~7; \
399 #if NO_UNALIGNED_ACCESS
400 #define WRITE32(td, v) \
402 ENSURE_CODE(td, 2); \
403 * (guint16 *)((td)->new_ip) = * (guint16 *)(v); \
404 * ((guint16 *)((td)->new_ip) + 1) = * ((guint16 *)(v) + 1); \
408 #define WRITE64(td, v) \
410 ENSURE_CODE(td, 4); \
411 * (guint16 *)((td)->new_ip) = * (guint16 *)(v); \
412 * ((guint16 *)((td)->new_ip) + 1) = * ((guint16 *)(v) + 1); \
413 * ((guint16 *)((td)->new_ip) + 2) = * ((guint16 *)(v) + 2); \
414 * ((guint16 *)((td)->new_ip) + 3) = * ((guint16 *)(v) + 3); \
418 #define WRITE32(td, v) \
420 ENSURE_CODE(td, 2); \
421 * (guint32 *)((td)->new_ip) = * (guint32 *)(v); \
425 #define WRITE64(td, v) \
427 ENSURE_CODE(td, 4); \
428 * (guint64 *)((td)->new_ip) = * (guint64 *)(v); \
435 load_arg(TransformData
*td
, int n
)
438 MonoClass
*klass
= NULL
;
441 gboolean hasthis
= mono_method_signature (td
->method
)->hasthis
;
442 if (hasthis
&& n
== 0)
443 type
= &td
->method
->klass
->byval_arg
;
445 type
= mono_method_signature (td
->method
)->params
[hasthis
? n
- 1 : n
];
447 mt
= mint_type (type
);
448 if (mt
== MINT_TYPE_VT
) {
450 klass
= mono_class_from_mono_type (type
);
451 if (mono_method_signature (td
->method
)->pinvoke
)
452 size
= mono_class_native_size (klass
, NULL
);
454 size
= mono_class_value_size (klass
, NULL
);
456 if (hasthis
&& n
== 0) {
458 ADD_CODE (td
, MINT_LDARG_P
);
459 ADD_CODE (td
, td
->rtm
->arg_offsets
[n
]); /* FIX for large offset */
463 ADD_CODE (td
, MINT_LDARG_VT
);
464 ADD_CODE (td
, td
->rtm
->arg_offsets
[n
]); /* FIX for large offset */
468 if (hasthis
&& n
== 0) {
470 ADD_CODE (td
, MINT_LDARG_P
);
471 ADD_CODE (td
, td
->rtm
->arg_offsets
[n
]); /* FIX for large offset */
474 ADD_CODE(td
, MINT_LDARG_I1
+ (mt
- MINT_TYPE_I1
));
475 ADD_CODE(td
, td
->rtm
->arg_offsets
[n
]); /* FIX for large offset */
476 if (mt
== MINT_TYPE_O
)
477 klass
= mono_class_from_mono_type (type
);
480 PUSH_TYPE(td
, stack_type
[mt
], klass
);
484 store_arg(TransformData
*td
, int n
)
490 gboolean hasthis
= mono_method_signature (td
->method
)->hasthis
;
491 if (hasthis
&& n
== 0)
492 type
= &td
->method
->klass
->byval_arg
;
494 type
= mono_method_signature (td
->method
)->params
[n
- !!hasthis
];
496 mt
= mint_type (type
);
497 if (mt
== MINT_TYPE_VT
) {
499 g_error ("data.klass");
500 if (mono_method_signature (td
->method
)->pinvoke
)
501 size
= mono_class_native_size (type
->data
.klass
, NULL
);
503 size
= mono_class_value_size (type
->data
.klass
, NULL
);
504 ADD_CODE(td
, MINT_STARG_VT
);
507 if (td
->sp
[-1].type
== STACK_TYPE_VT
)
510 ADD_CODE(td
, MINT_STARG_I1
+ (mt
- MINT_TYPE_I1
));
511 ADD_CODE(td
, td
->rtm
->arg_offsets
[n
]);
517 store_inarg(TransformData
*td
, int n
)
520 gboolean hasthis
= mono_method_signature (td
->method
)->hasthis
;
521 if (hasthis
&& n
== 0)
522 type
= &td
->method
->klass
->byval_arg
;
524 type
= mono_method_signature (td
->method
)->params
[n
- !!hasthis
];
526 int mt
= mint_type (type
);
527 if (hasthis
&& n
== 0) {
528 ADD_CODE (td
, MINT_STINARG_P
);
532 if (mt
== MINT_TYPE_VT
) {
533 MonoClass
*klass
= mono_class_from_mono_type (type
);
535 if (mono_method_signature (td
->method
)->pinvoke
)
536 size
= mono_class_native_size (klass
, NULL
);
538 size
= mono_class_value_size (klass
, NULL
);
539 ADD_CODE(td
, MINT_STINARG_VT
);
543 ADD_CODE(td
, MINT_STINARG_I1
+ (mt
- MINT_TYPE_I1
));
549 load_local(TransformData
*td
, int n
)
551 MonoType
*type
= td
->header
->locals
[n
];
552 int mt
= mint_type (type
);
553 int offset
= td
->rtm
->local_offsets
[n
];
554 MonoClass
*klass
= NULL
;
555 if (mt
== MINT_TYPE_VT
) {
556 klass
= mono_class_from_mono_type (type
);
557 gint32 size
= mono_class_value_size (klass
, NULL
);
559 ADD_CODE(td
, MINT_LDLOC_VT
);
560 ADD_CODE(td
, offset
); /*FIX for large offset */
563 g_assert (mt
< MINT_TYPE_VT
);
564 if (mt
== MINT_TYPE_I4
&& !td
->is_bb_start
[td
->in_start
- td
->il_code
] && td
->last_new_ip
!= NULL
&&
565 td
->last_new_ip
[0] == MINT_STLOC_I4
&& td
->last_new_ip
[1] == offset
) {
566 td
->last_new_ip
[0] = MINT_STLOC_NP_I4
;
567 } else if (mt
== MINT_TYPE_O
&& !td
->is_bb_start
[td
->in_start
- td
->il_code
] && td
->last_new_ip
!= NULL
&&
568 td
->last_new_ip
[0] == MINT_STLOC_O
&& td
->last_new_ip
[1] == offset
) {
569 td
->last_new_ip
[0] = MINT_STLOC_NP_O
;
571 ADD_CODE(td
, MINT_LDLOC_I1
+ (mt
- MINT_TYPE_I1
));
572 ADD_CODE(td
, offset
); /*FIX for large offset */
574 if (mt
== MINT_TYPE_O
)
575 klass
= mono_class_from_mono_type (type
);
577 PUSH_TYPE(td
, stack_type
[mt
], klass
);
581 store_local(TransformData
*td
, int n
)
583 MonoType
*type
= td
->header
->locals
[n
];
584 int mt
= mint_type (type
);
585 int offset
= td
->rtm
->local_offsets
[n
];
587 #if SIZEOF_VOID_P == 8
588 if (td
->sp
[-1].type
== STACK_TYPE_I4
&& stack_type
[mt
] == STACK_TYPE_I8
) {
589 ADD_CODE(td
, MINT_CONV_I8_I4
);
590 td
->sp
[-1].type
= STACK_TYPE_I8
;
593 if (!can_store(td
->sp
[-1].type
, stack_type
[mt
])) {
594 g_warning("%s.%s: Store local stack type mismatch %d %d",
595 td
->method
->klass
->name
, td
->method
->name
,
596 stack_type
[mt
], td
->sp
[-1].type
);
598 if (mt
== MINT_TYPE_VT
) {
599 MonoClass
*klass
= mono_class_from_mono_type (type
);
600 gint32 size
= mono_class_value_size (klass
, NULL
);
601 ADD_CODE(td
, MINT_STLOC_VT
);
602 ADD_CODE(td
, offset
); /*FIX for large offset */
604 if (td
->sp
[-1].type
== STACK_TYPE_VT
)
607 g_assert (mt
< MINT_TYPE_VT
);
608 ADD_CODE(td
, MINT_STLOC_I1
+ (mt
- MINT_TYPE_I1
));
609 ADD_CODE(td
, offset
); /*FIX for large offset */
614 #define SIMPLE_OP(td, op) \
621 get_data_item_index (TransformData
*td
, void *ptr
)
623 gpointer p
= g_hash_table_lookup (td
->data_hash
, ptr
);
626 return GPOINTER_TO_UINT (p
) - 1;
627 if (td
->max_data_items
== td
->n_data_items
) {
628 td
->max_data_items
= td
->n_data_items
== 0 ? 16 : 2 * td
->max_data_items
;
629 td
->data_items
= g_realloc (td
->data_items
, td
->max_data_items
* sizeof(td
->data_items
[0]));
631 index
= td
->n_data_items
;
632 td
->data_items
[index
] = ptr
;
634 g_hash_table_insert (td
->data_hash
, ptr
, GUINT_TO_POINTER (index
+ 1));
639 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
)
641 MonoImage
*image
= method
->klass
->image
;
642 MonoMethodSignature
*csignature
;
644 int virtual = *td
->ip
== CEE_CALLVIRT
;
645 int calli
= *td
->ip
== CEE_CALLI
|| *td
->ip
== CEE_MONO_CALLI_EXTRA_ARG
;
647 guint32 vt_stack_used
= 0;
648 guint32 vt_res_size
= 0;
653 guint32 token
= read32 (td
->ip
+ 1);
655 if (target_method
== NULL
) {
658 native
= (method
->wrapper_type
!= MONO_WRAPPER_DELEGATE_INVOKE
&& td
->sp
[-1].type
== STACK_TYPE_I
);
660 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
661 csignature
= (MonoMethodSignature
*)mono_method_get_wrapper_data (method
, token
);
663 csignature
= mono_metadata_parse_signature (image
, token
);
665 if (generic_context
) {
666 csignature
= mono_inflate_generic_signature (csignature
, generic_context
, &error
);
667 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
670 target_method
= NULL
;
672 if (method
->wrapper_type
== MONO_WRAPPER_NONE
)
673 target_method
= mono_get_method_full (image
, token
, NULL
, generic_context
);
675 target_method
= (MonoMethod
*)mono_method_get_wrapper_data (method
, token
);
676 csignature
= mono_method_signature (target_method
);
677 if (target_method
->klass
== mono_defaults
.string_class
) {
678 if (target_method
->name
[0] == 'g') {
679 if (strcmp (target_method
->name
, "get_Chars") == 0)
681 else if (strcmp (target_method
->name
, "get_Length") == 0)
684 } else if (mono_class_is_subclass_of (target_method
->klass
, mono_defaults
.array_class
, FALSE
)) {
685 if (!strcmp (target_method
->name
, "get_Rank")) {
686 op
= MINT_ARRAY_RANK
;
687 } else if (!strcmp (target_method
->name
, "get_Length")) {
689 } else if (!strcmp (target_method
->name
, "Address")) {
690 op
= readonly
? MINT_LDELEMA
: MINT_LDELEMA_TC
;
692 } else if (target_method
&& generic_context
) {
693 csignature
= mono_inflate_generic_signature (csignature
, generic_context
, &error
);
694 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
695 target_method
= mono_class_inflate_generic_method_checked (target_method
, generic_context
, &error
);
696 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
700 csignature
= mono_method_signature (target_method
);
703 if (constrained_class
) {
704 if (constrained_class
->enumtype
&& !strcmp (target_method
->name
, "GetHashCode")) {
705 /* Use the corresponding method from the base type to avoid boxing */
706 MonoType
*base_type
= mono_class_enum_basetype (constrained_class
);
707 g_assert (base_type
);
708 constrained_class
= mono_class_from_mono_type (base_type
);
709 target_method
= mono_class_get_method_from_name (constrained_class
, target_method
->name
, 0);
710 g_assert (target_method
);
714 if (constrained_class
) {
715 mono_class_setup_vtable (constrained_class
);
717 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
);
719 target_method
= mono_get_method_constrained_with_method (image
, target_method
, constrained_class
, generic_context
, &error
);
721 g_print (" : %s::%s. %s (%p)\n", target_method
->klass
->name
, target_method
->name
, mono_signature_full_name (target_method
->signature
), target_method
);
723 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
724 mono_class_setup_vtable (target_method
->klass
);
726 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
)) {
727 if (target_method
->klass
== mono_defaults
.enum_class
&& (td
->sp
- csignature
->param_count
- 1)->type
== STACK_TYPE_MP
) {
728 /* managed pointer on the stack, we need to deref that puppy */
729 ADD_CODE (td
, MINT_LDIND_I
);
730 ADD_CODE (td
, csignature
->param_count
);
732 ADD_CODE (td
, MINT_BOX
);
733 ADD_CODE (td
, get_data_item_index (td
, constrained_class
));
734 ADD_CODE (td
, csignature
->param_count
);
735 } else if (!constrained_class
->valuetype
) {
736 /* managed pointer on the stack, we need to deref that puppy */
737 ADD_CODE (td
, MINT_LDIND_I
);
738 ADD_CODE (td
, csignature
->param_count
);
740 if (target_method
->klass
->valuetype
) {
743 /* Interface method */
746 mono_class_setup_vtable (constrained_class
);
747 ioffset
= mono_class_interface_offset (constrained_class
, target_method
->klass
);
749 g_error ("type load error: constrained_class");
750 slot
= mono_method_get_vtable_slot (target_method
);
752 g_error ("type load error: target_method->klass");
753 target_method
= constrained_class
->vtable
[ioffset
+ slot
];
755 if (target_method
->klass
== mono_defaults
.enum_class
) {
756 if ((td
->sp
- csignature
->param_count
- 1)->type
== STACK_TYPE_MP
) {
757 /* managed pointer on the stack, we need to deref that puppy */
758 ADD_CODE (td
, MINT_LDIND_I
);
759 ADD_CODE (td
, csignature
->param_count
);
761 ADD_CODE (td
, MINT_BOX
);
762 ADD_CODE (td
, get_data_item_index (td
, constrained_class
));
763 ADD_CODE (td
, csignature
->param_count
);
771 mono_class_init (target_method
->klass
);
773 CHECK_STACK (td
, csignature
->param_count
+ csignature
->hasthis
);
774 if (!calli
&& (!virtual || (target_method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
) == 0) &&
775 (target_method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) == 0 &&
776 (target_method
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) == 0) {
777 int called_inited
= mono_class_vtable (domain
, target_method
->klass
)->initialized
;
778 MonoMethodHeader
*mheader
= mono_method_get_header (target_method
);
780 if (/*mono_metadata_signature_equal (method->signature, target_method->signature) */ method
== target_method
&& *(td
->ip
+ 5) == CEE_RET
) {
782 if (mono_interp_traceopt
)
783 g_print ("Optimize tail call of %s.%s\n", target_method
->klass
->name
, target_method
->name
);
784 for (i
= csignature
->param_count
- 1; i
>= 0; --i
)
785 store_arg (td
, i
+ csignature
->hasthis
);
787 ADD_CODE(td
, MINT_BR_S
);
788 offset
= body_start_offset
- ((td
->new_ip
- 1) - td
->new_code
);
789 ADD_CODE(td
, offset
);
790 if (!is_bb_start
[td
->ip
+ 5 - td
->il_code
])
791 ++td
->ip
; /* gobble the CEE_RET if it isn't branched to */
795 /* mheader might not exist if this is a delegate invoc, etc */
796 if (mheader
&& *mheader
->code
== CEE_RET
&& called_inited
) {
797 if (mono_interp_traceopt
)
798 g_print ("Inline (empty) call of %s.%s\n", target_method
->klass
->name
, target_method
->name
);
799 for (i
= 0; i
< csignature
->param_count
; i
++)
800 ADD_CODE (td
, MINT_POP
); /*FIX: vt */
802 if (csignature
->hasthis
) {
804 ADD_CODE(td
, MINT_CKNULL
);
805 ADD_CODE (td
, MINT_POP
);
808 td
->sp
-= csignature
->param_count
+ csignature
->hasthis
;
814 if (method
->wrapper_type
== MONO_WRAPPER_NONE
&& target_method
!= NULL
) {
815 if (target_method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
)
816 target_method
= mono_marshal_get_native_wrapper (target_method
, FALSE
, FALSE
);
817 if (!virtual && target_method
->iflags
& METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED
)
818 target_method
= mono_marshal_get_synchronized_wrapper (target_method
);
820 g_assert (csignature
->call_convention
== MONO_CALL_DEFAULT
|| csignature
->call_convention
== MONO_CALL_C
);
821 td
->sp
-= csignature
->param_count
+ !!csignature
->hasthis
;
822 for (i
= 0; i
< csignature
->param_count
; ++i
) {
823 if (td
->sp
[i
+ !!csignature
->hasthis
].type
== STACK_TYPE_VT
) {
825 MonoClass
*klass
= mono_class_from_mono_type (csignature
->params
[i
]);
826 if (csignature
->pinvoke
&& method
->wrapper_type
!= MONO_WRAPPER_NONE
)
827 size
= mono_class_native_size (klass
, NULL
);
829 size
= mono_class_value_size (klass
, NULL
);
830 size
= (size
+ 7) & ~7;
831 vt_stack_used
+= size
;
835 /* need to handle typedbyref ... */
836 if (csignature
->ret
->type
!= MONO_TYPE_VOID
) {
837 int mt
= mint_type(csignature
->ret
);
838 MonoClass
*klass
= mono_class_from_mono_type (csignature
->ret
);
839 if (mt
== MINT_TYPE_VT
) {
840 if (csignature
->pinvoke
&& method
->wrapper_type
!= MONO_WRAPPER_NONE
)
841 vt_res_size
= mono_class_native_size (klass
, NULL
);
843 vt_res_size
= mono_class_value_size (klass
, NULL
);
844 PUSH_VT(td
, vt_res_size
);
846 PUSH_TYPE(td
, stack_type
[mt
], klass
);
852 #if SIZEOF_VOID_P == 8
853 if (op
== MINT_LDLEN
)
854 ADD_CODE (td
, MINT_CONV_I4_I8
);
856 if (op
== MINT_LDELEMA
|| op
== MINT_LDELEMA_TC
) {
857 ADD_CODE (td
, get_data_item_index (td
, target_method
->klass
));
858 ADD_CODE (td
, 1 + target_method
->klass
->rank
);
862 ADD_CODE(td
, native
? MINT_CALLI_NAT
: MINT_CALLI
);
864 ADD_CODE(td
, is_void
? MINT_VCALLVIRT
: MINT_CALLVIRT
);
866 ADD_CODE(td
, is_void
? MINT_VCALL
: MINT_CALL
);
869 ADD_CODE(td
, get_data_item_index (td
, (void *)csignature
));
871 ADD_CODE(td
, get_data_item_index (td
, (void *)mono_interp_get_runtime_method (domain
, target_method
, &error
)));
872 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
876 if (vt_stack_used
!= 0 || vt_res_size
!= 0) {
877 ADD_CODE(td
, MINT_VTRESULT
);
878 ADD_CODE(td
, vt_res_size
);
879 WRITE32(td
, &vt_stack_used
);
880 td
->vt_sp
-= vt_stack_used
;
885 generate (MonoMethod
*method
, RuntimeMethod
*rtm
, unsigned char *is_bb_start
, MonoGenericContext
*generic_context
)
887 MonoMethodHeader
*header
= mono_method_get_header (method
);
888 MonoMethodSignature
*signature
= mono_method_signature (method
);
889 MonoImage
*image
= method
->klass
->image
;
890 MonoDomain
*domain
= mono_domain_get ();
891 MonoClass
*constrained_class
= NULL
;
893 int offset
, mt
, i
, i32
;
894 gboolean readonly
= FALSE
;
896 MonoClassField
*field
;
897 const unsigned char *end
;
898 int new_in_start_offset
;
899 int body_start_offset
;
903 int generating_code
= 1;
905 memset(&td
, 0, sizeof(td
));
908 td
.is_bb_start
= is_bb_start
;
909 td
.il_code
= header
->code
;
910 td
.code_size
= header
->code_size
;
912 td
.max_code_size
= td
.code_size
;
913 td
.new_code
= (unsigned short *)g_malloc(td
.max_code_size
* sizeof(gushort
));
914 td
.new_code_end
= td
.new_code
+ td
.max_code_size
;
915 td
.in_offsets
= g_malloc0(header
->code_size
* sizeof(int));
916 td
.forward_refs
= g_malloc(header
->code_size
* sizeof(int));
917 td
.stack_state
= g_malloc0(header
->code_size
* sizeof(StackInfo
*));
918 td
.stack_height
= g_malloc(header
->code_size
* sizeof(int));
919 td
.vt_stack_size
= g_malloc(header
->code_size
* sizeof(int));
921 td
.max_data_items
= 0;
922 td
.data_items
= NULL
;
923 td
.data_hash
= g_hash_table_new (NULL
, NULL
);
924 rtm
->data_items
= td
.data_items
;
925 for (i
= 0; i
< header
->code_size
; i
++) {
926 td
.forward_refs
[i
] = -1;
927 td
.stack_height
[i
] = -1;
929 td
.new_ip
= td
.new_code
;
930 td
.last_new_ip
= NULL
;
932 td
.stack
= g_malloc0 ((header
->max_stack
+ 1) * sizeof (td
.stack
[0]));
934 td
.max_stack_height
= 0;
936 for (i
= 0; i
< header
->num_clauses
; i
++) {
937 MonoExceptionClause
*c
= header
->clauses
+ i
;
938 td
.stack_height
[c
->handler_offset
] = 0;
939 td
.vt_stack_size
[c
->handler_offset
] = 0;
940 td
.is_bb_start
[c
->handler_offset
] = 1;
942 td
.stack_height
[c
->handler_offset
] = 1;
943 td
.stack_state
[c
->handler_offset
] = g_malloc0(sizeof(StackInfo
));
944 td
.stack_state
[c
->handler_offset
][0].type
= STACK_TYPE_O
;
945 td
.stack_state
[c
->handler_offset
][0].klass
= NULL
; /*FIX*/
948 td
.ip
= header
->code
;
949 end
= td
.ip
+ header
->code_size
;
951 if (mono_interp_traceopt
) {
952 char *tmp
= mono_disasm_code (NULL
, method
, td
.ip
, end
);
953 char *name
= mono_method_full_name (method
, TRUE
);
954 g_print ("Method %s, original code:\n", name
);
955 g_print ("%s\n", tmp
);
960 if (signature
->hasthis
)
961 store_inarg (&td
, 0);
962 for (i
= 0; i
< signature
->param_count
; i
++)
963 store_inarg (&td
, i
+ !!signature
->hasthis
);
965 body_start_offset
= td
.new_ip
- td
.new_code
;
967 for (i
= 0; i
< header
->num_locals
; i
++) {
968 int mt
= mint_type(header
->locals
[i
]);
969 if (mt
== MINT_TYPE_VT
|| mt
== MINT_TYPE_O
|| mt
== MINT_TYPE_P
) {
970 ADD_CODE(&td
, MINT_INITLOCALS
);
975 while (td
.ip
< end
) {
978 g_assert (td
.sp
>= td
.stack
);
979 g_assert (td
.vt_sp
< 0x10000000);
980 in_offset
= td
.ip
- header
->code
;
981 td
.in_offsets
[in_offset
] = td
.new_ip
- td
.new_code
;
982 new_in_start_offset
= td
.new_ip
- td
.new_code
;
984 while (td
.forward_refs
[in_offset
] >= 0) {
985 int j
= td
.forward_refs
[in_offset
];
987 td
.forward_refs
[in_offset
] = td
.forward_refs
[j
];
988 if (td
.in_offsets
[j
] < 0) {
989 int old_switch_offset
= -td
.in_offsets
[j
];
990 int new_switch_offset
= td
.in_offsets
[old_switch_offset
];
991 int switch_case
= (j
- old_switch_offset
- 5) / 4;
992 int n_cases
= read32 (header
->code
+ old_switch_offset
+ 1);
993 offset
= (td
.new_ip
- td
.new_code
) - (new_switch_offset
+ 2 * n_cases
+ 3);
994 slot
= new_switch_offset
+ 3 + 2 * switch_case
;
995 td
.new_code
[slot
] = * (unsigned short *)(&offset
);
996 td
.new_code
[slot
+ 1] = * ((unsigned short *)&offset
+ 1);
998 int op
= td
.new_code
[td
.in_offsets
[j
]];
999 if (mono_interp_opargtype
[op
] == MintOpShortBranch
) {
1000 offset
= (td
.new_ip
- td
.new_code
) - td
.in_offsets
[j
];
1001 g_assert (offset
<= 32767);
1002 slot
= td
.in_offsets
[j
] + 1;
1003 td
.new_code
[slot
] = offset
;
1005 offset
= (td
.new_ip
- td
.new_code
) - td
.in_offsets
[j
];
1006 slot
= td
.in_offsets
[j
] + 1;
1007 td
.new_code
[slot
] = * (unsigned short *)(&offset
);
1008 td
.new_code
[slot
+ 1] = * ((unsigned short *)&offset
+ 1);
1012 if (td
.stack_height
[in_offset
] >= 0) {
1013 g_assert (is_bb_start
[in_offset
]);
1014 if (td
.stack_height
[in_offset
] > 0)
1015 memcpy (td
.stack
, td
.stack_state
[in_offset
], td
.stack_height
[in_offset
] * sizeof(td
.stack
[0]));
1016 td
.sp
= td
.stack
+ td
.stack_height
[in_offset
];
1017 td
.vt_sp
= td
.vt_stack_size
[in_offset
];
1019 if (is_bb_start
[in_offset
]) {
1020 generating_code
= 1;
1022 if (!generating_code
) {
1023 while (td
.ip
< end
&& !is_bb_start
[td
.ip
- td
.il_code
])
1027 if (mono_interp_traceopt
> 1) {
1028 printf("IL_%04lx %s %-10s -> IL_%04lx, sp %ld, %s %-12s vt_sp %u (max %u)\n",
1030 td
.is_bb_start
[td
.ip
- td
.il_code
] == 3 ? "<>" :
1031 td
.is_bb_start
[td
.ip
- td
.il_code
] == 2 ? "< " :
1032 td
.is_bb_start
[td
.ip
- td
.il_code
] == 1 ? " >" : " ",
1033 mono_opcode_name (*td
.ip
), td
.new_ip
- td
.new_code
, td
.sp
- td
.stack
,
1034 td
.sp
> td
.stack
? stack_type_string
[td
.sp
[-1].type
] : " ",
1035 (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
) : "",
1036 td
.vt_sp
, td
.max_vt_sp
);
1044 SIMPLE_OP(td
, MINT_BREAK
);
1050 load_arg (&td
, *td
.ip
- CEE_LDARG_0
);
1057 load_local (&td
, *td
.ip
- CEE_LDLOC_0
);
1064 store_local (&td
, *td
.ip
- CEE_STLOC_0
);
1068 load_arg (&td
, ((guint8
*)td
.ip
)[1]);
1071 case CEE_LDARGA_S
: {
1072 /* NOTE: n includes this */
1073 int n
= ((guint8
*)td
.ip
)[1];
1074 if (n
== 0 && signature
->hasthis
) {
1075 g_error ("LDTHISA: NOPE");
1076 ADD_CODE(&td
, MINT_LDTHISA
);
1079 ADD_CODE(&td
, MINT_LDARGA
);
1080 ADD_CODE(&td
, td
.rtm
->arg_offsets
[n
]);
1082 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_MP
);
1087 store_arg (&td
, ((guint8
*)td
.ip
)[1]);
1091 load_local (&td
, ((guint8
*)td
.ip
)[1]);
1095 ADD_CODE(&td
, MINT_LDLOCA_S
);
1096 ADD_CODE(&td
, td
.rtm
->local_offsets
[((guint8
*)td
.ip
)[1]]);
1097 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_MP
);
1101 store_local (&td
, ((guint8
*)td
.ip
)[1]);
1105 SIMPLE_OP(td
, MINT_LDNULL
);
1106 PUSH_TYPE(&td
, STACK_TYPE_O
, NULL
);
1109 SIMPLE_OP(td
, MINT_LDC_I4_M1
);
1110 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I4
);
1113 if (!td
.is_bb_start
[td
.ip
+ 1 - td
.il_code
] && td
.ip
[1] == 0xfe && td
.ip
[2] == CEE_CEQ
&&
1114 td
.sp
> td
.stack
&& td
.sp
[-1].type
== STACK_TYPE_I4
) {
1115 SIMPLE_OP(td
, MINT_CEQ0_I4
);
1118 SIMPLE_OP(td
, MINT_LDC_I4_0
);
1119 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I4
);
1123 if (!td
.is_bb_start
[td
.ip
+ 1 - td
.il_code
] &&
1124 (td
.ip
[1] == CEE_ADD
|| td
.ip
[1] == CEE_SUB
) && td
.sp
[-1].type
== STACK_TYPE_I4
) {
1125 ADD_CODE(&td
, td
.ip
[1] == CEE_ADD
? MINT_ADD1_I4
: MINT_SUB1_I4
);
1128 SIMPLE_OP(td
, MINT_LDC_I4_1
);
1129 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I4
);
1139 SIMPLE_OP(td
, (*td
.ip
- CEE_LDC_I4_0
) + MINT_LDC_I4_0
);
1140 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I4
);
1143 ADD_CODE(&td
, MINT_LDC_I4_S
);
1144 ADD_CODE(&td
, ((gint8
*) td
.ip
) [1]);
1146 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I4
);
1149 i32
= read32 (td
.ip
+ 1);
1150 ADD_CODE(&td
, MINT_LDC_I4
);
1153 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I4
);
1156 gint64 val
= read64 (td
.ip
+ 1);
1157 ADD_CODE(&td
, MINT_LDC_I8
);
1160 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I8
);
1165 readr4 (td
.ip
+ 1, &val
);
1166 ADD_CODE(&td
, MINT_LDC_R4
);
1169 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_R8
);
1174 readr8 (td
.ip
+ 1, &val
);
1175 ADD_CODE(&td
, MINT_LDC_R8
);
1178 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_R8
);
1182 int type
= td
.sp
[-1].type
;
1183 MonoClass
*klass
= td
.sp
[-1].klass
;
1184 if (td
.sp
[-1].type
== STACK_TYPE_VT
) {
1185 gint32 size
= mono_class_value_size (klass
, NULL
);
1187 ADD_CODE(&td
, MINT_DUP_VT
);
1188 WRITE32(&td
, &size
);
1191 SIMPLE_OP(td
, MINT_DUP
);
1192 PUSH_TYPE(&td
, type
, klass
);
1196 CHECK_STACK(&td
, 1);
1197 SIMPLE_OP(td
, MINT_POP
);
1199 if (td
.sp
[-1].type
== STACK_TYPE_VT
) {
1200 int size
= mono_class_value_size (td
.sp
[-1].klass
, NULL
);
1201 size
= (size
+ 7) & ~7;
1202 ADD_CODE(&td
, MINT_VTRESULT
);
1204 WRITE32(&td
, &size
);
1211 if (td
.sp
> td
.stack
)
1212 g_warning ("CEE_JMP: stack must be empty");
1213 token
= read32 (td
.ip
+ 1);
1214 m
= mono_get_method_full (image
, token
, NULL
, generic_context
);
1215 ADD_CODE (&td
, MINT_JMP
);
1216 ADD_CODE (&td
, get_data_item_index (&td
, mono_interp_get_runtime_method (domain
, m
, &error
)));
1217 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
1221 case CEE_CALLVIRT
: /* Fall through */
1222 case CEE_CALLI
: /* Fall through */
1224 interp_transform_call (&td
, method
, NULL
, domain
, generic_context
, is_bb_start
, body_start_offset
, constrained_class
, readonly
);
1225 constrained_class
= NULL
;
1231 if (signature
->ret
->type
!= MONO_TYPE_VOID
) {
1233 MonoClass
*klass
= mono_class_from_mono_type (signature
->ret
);
1234 if (mint_type (&klass
->byval_arg
) == MINT_TYPE_VT
) {
1235 vt_size
= mono_class_value_size (klass
, NULL
);
1236 vt_size
= (vt_size
+ 7) & ~7;
1239 if (td
.sp
> td
.stack
)
1240 g_warning ("%s.%s: CEE_RET: more values on stack: %d", td
.method
->klass
->name
, td
.method
->name
, td
.sp
- td
.stack
);
1241 if (td
.vt_sp
!= vt_size
)
1242 g_error ("%s.%s: CEE_RET: value type stack: %d vs. %d", td
.method
->klass
->name
, td
.method
->name
, td
.vt_sp
, vt_size
);
1244 SIMPLE_OP(td
, signature
->ret
->type
== MONO_TYPE_VOID
? MINT_RET_VOID
: MINT_RET
);
1246 ADD_CODE(&td
, MINT_RET_VT
);
1247 WRITE32(&td
, &vt_size
);
1250 generating_code
= 0;
1254 handle_branch (&td
, MINT_BR_S
, MINT_BR
, 5 + read32 (td
.ip
+ 1));
1256 generating_code
= 0;
1259 handle_branch (&td
, MINT_BR_S
, MINT_BR
, 2 + (gint8
)td
.ip
[1]);
1261 generating_code
= 0;
1264 one_arg_branch (&td
, MINT_BRFALSE_I4
, 5 + read32 (td
.ip
+ 1));
1268 one_arg_branch (&td
, MINT_BRFALSE_I4
, 2 + (gint8
)td
.ip
[1]);
1272 one_arg_branch (&td
, MINT_BRTRUE_I4
, 5 + read32 (td
.ip
+ 1));
1276 one_arg_branch (&td
, MINT_BRTRUE_I4
, 2 + (gint8
)td
.ip
[1]);
1280 two_arg_branch (&td
, MINT_BEQ_I4
, 5 + read32 (td
.ip
+ 1));
1284 two_arg_branch (&td
, MINT_BEQ_I4
, 2 + (gint8
) td
.ip
[1]);
1288 two_arg_branch (&td
, MINT_BGE_I4
, 5 + read32 (td
.ip
+ 1));
1292 two_arg_branch (&td
, MINT_BGE_I4
, 2 + (gint8
) td
.ip
[1]);
1296 two_arg_branch (&td
, MINT_BGT_I4
, 5 + read32 (td
.ip
+ 1));
1300 two_arg_branch (&td
, MINT_BGT_I4
, 2 + (gint8
) td
.ip
[1]);
1304 two_arg_branch (&td
, MINT_BLT_I4
, 5 + read32 (td
.ip
+ 1));
1308 two_arg_branch (&td
, MINT_BLT_I4
, 2 + (gint8
) td
.ip
[1]);
1312 two_arg_branch (&td
, MINT_BLE_I4
, 5 + read32 (td
.ip
+ 1));
1316 two_arg_branch (&td
, MINT_BLE_I4
, 2 + (gint8
) td
.ip
[1]);
1320 two_arg_branch (&td
, MINT_BNE_UN_I4
, 5 + read32 (td
.ip
+ 1));
1324 two_arg_branch (&td
, MINT_BNE_UN_I4
, 2 + (gint8
) td
.ip
[1]);
1328 two_arg_branch (&td
, MINT_BGE_UN_I4
, 5 + read32 (td
.ip
+ 1));
1332 two_arg_branch (&td
, MINT_BGE_UN_I4
, 2 + (gint8
) td
.ip
[1]);
1336 two_arg_branch (&td
, MINT_BGT_UN_I4
, 5 + read32 (td
.ip
+ 1));
1340 two_arg_branch (&td
, MINT_BGT_UN_I4
, 2 + (gint8
) td
.ip
[1]);
1344 two_arg_branch (&td
, MINT_BLE_UN_I4
, 5 + read32 (td
.ip
+ 1));
1348 two_arg_branch (&td
, MINT_BLE_UN_I4
, 2 + (gint8
) td
.ip
[1]);
1352 two_arg_branch (&td
, MINT_BLT_UN_I4
, 5 + read32 (td
.ip
+ 1));
1356 two_arg_branch (&td
, MINT_BLT_UN_I4
, 2 + (gint8
) td
.ip
[1]);
1361 const unsigned char *next_ip
;
1362 const unsigned char *base_ip
= td
.ip
;
1363 unsigned short *next_new_ip
;
1366 ADD_CODE(&td
, MINT_SWITCH
);
1367 ADD_CODE(&td
, * (unsigned short *)(&n
));
1368 ADD_CODE(&td
, * ((unsigned short *)&n
+ 1));
1370 next_ip
= td
.ip
+ n
* 4;
1371 next_new_ip
= td
.new_ip
+ n
* 2;
1372 for (i
= 0; i
< n
; i
++) {
1373 offset
= read32 (td
.ip
);
1374 target
= next_ip
- td
.il_code
+ offset
;
1376 target
= td
.in_offsets
[target
] - (next_new_ip
- td
.new_code
);
1378 int prev
= td
.forward_refs
[target
];
1379 td
.forward_refs
[td
.ip
- td
.il_code
] = prev
;
1380 td
.forward_refs
[target
] = td
.ip
- td
.il_code
;
1381 td
.in_offsets
[td
.ip
- td
.il_code
] = - (base_ip
- td
.il_code
);
1383 ADD_CODE(&td
, * (unsigned short *)(&target
));
1384 ADD_CODE(&td
, * ((unsigned short *)&target
+ 1));
1391 CHECK_STACK (&td
, 1);
1392 SIMPLE_OP (td
, MINT_LDIND_I1
);
1393 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1396 CHECK_STACK (&td
, 1);
1397 SIMPLE_OP (td
, MINT_LDIND_U1
);
1398 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1401 CHECK_STACK (&td
, 1);
1402 SIMPLE_OP (td
, MINT_LDIND_I2
);
1403 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1406 CHECK_STACK (&td
, 1);
1407 SIMPLE_OP (td
, MINT_LDIND_U2
);
1408 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1411 CHECK_STACK (&td
, 1);
1412 SIMPLE_OP (td
, MINT_LDIND_I4
);
1413 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1416 CHECK_STACK (&td
, 1);
1417 SIMPLE_OP (td
, MINT_LDIND_U4
);
1418 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1421 CHECK_STACK (&td
, 1);
1422 SIMPLE_OP (td
, MINT_LDIND_I8
);
1423 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
1426 CHECK_STACK (&td
, 1);
1427 SIMPLE_OP (td
, MINT_LDIND_I
);
1429 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I
);
1432 CHECK_STACK (&td
, 1);
1433 SIMPLE_OP (td
, MINT_LDIND_R4
);
1434 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
1437 CHECK_STACK (&td
, 1);
1438 SIMPLE_OP (td
, MINT_LDIND_R8
);
1439 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
1442 CHECK_STACK (&td
, 1);
1443 SIMPLE_OP (td
, MINT_LDIND_REF
);
1444 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_O
);
1447 CHECK_STACK (&td
, 2);
1448 SIMPLE_OP (td
, MINT_STIND_REF
);
1452 CHECK_STACK (&td
, 2);
1453 SIMPLE_OP (td
, MINT_STIND_I1
);
1457 CHECK_STACK (&td
, 2);
1458 SIMPLE_OP (td
, MINT_STIND_I2
);
1462 CHECK_STACK (&td
, 2);
1463 SIMPLE_OP (td
, MINT_STIND_I4
);
1467 CHECK_STACK (&td
, 2);
1468 SIMPLE_OP (td
, MINT_STIND_I
);
1472 CHECK_STACK (&td
, 2);
1473 SIMPLE_OP (td
, MINT_STIND_I8
);
1477 CHECK_STACK (&td
, 2);
1478 SIMPLE_OP (td
, MINT_STIND_R4
);
1482 CHECK_STACK (&td
, 2);
1483 SIMPLE_OP (td
, MINT_STIND_R8
);
1487 binary_arith_op(&td
, MINT_ADD_I4
);
1491 binary_arith_op(&td
, MINT_SUB_I4
);
1495 binary_arith_op(&td
, MINT_MUL_I4
);
1499 binary_arith_op(&td
, MINT_DIV_I4
);
1503 binary_arith_op(&td
, MINT_DIV_UN_I4
);
1507 binary_int_op (&td
, MINT_REM_I4
);
1511 binary_int_op (&td
, MINT_REM_UN_I4
);
1515 binary_int_op (&td
, MINT_AND_I4
);
1519 binary_int_op (&td
, MINT_OR_I4
);
1523 binary_int_op (&td
, MINT_XOR_I4
);
1527 shift_op (&td
, MINT_SHL_I4
);
1531 shift_op (&td
, MINT_SHR_I4
);
1535 shift_op (&td
, MINT_SHR_UN_I4
);
1539 unary_arith_op (&td
, MINT_NEG_I4
);
1543 unary_arith_op (&td
, MINT_NOT_I4
);
1547 CHECK_STACK (&td
, 1);
1548 switch (td
.sp
[-1].type
) {
1550 ADD_CODE(&td
, MINT_CONV_U1_R8
);
1553 ADD_CODE(&td
, MINT_CONV_U1_I4
);
1556 ADD_CODE(&td
, MINT_CONV_U1_I8
);
1559 g_assert_not_reached ();
1562 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1565 CHECK_STACK (&td
, 1);
1566 switch (td
.sp
[-1].type
) {
1568 ADD_CODE(&td
, MINT_CONV_I1_R8
);
1571 ADD_CODE(&td
, MINT_CONV_I1_I4
);
1574 ADD_CODE(&td
, MINT_CONV_I1_I8
);
1577 g_assert_not_reached ();
1580 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1583 CHECK_STACK (&td
, 1);
1584 switch (td
.sp
[-1].type
) {
1586 ADD_CODE(&td
, MINT_CONV_U2_R8
);
1589 ADD_CODE(&td
, MINT_CONV_U2_I4
);
1592 ADD_CODE(&td
, MINT_CONV_U2_I8
);
1595 g_assert_not_reached ();
1598 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1601 CHECK_STACK (&td
, 1);
1602 switch (td
.sp
[-1].type
) {
1604 ADD_CODE(&td
, MINT_CONV_I2_R8
);
1607 ADD_CODE(&td
, MINT_CONV_I2_I4
);
1610 ADD_CODE(&td
, MINT_CONV_I2_I8
);
1613 g_assert_not_reached ();
1616 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1619 CHECK_STACK (&td
, 1);
1620 switch (td
.sp
[-1].type
) {
1622 #if SIZEOF_VOID_P == 4
1623 ADD_CODE(&td
, MINT_CONV_U4_R8
);
1625 ADD_CODE(&td
, MINT_CONV_U8_R8
);
1629 #if SIZEOF_VOID_P == 8
1630 ADD_CODE(&td
, MINT_CONV_U8_I4
);
1634 #if SIZEOF_VOID_P == 4
1635 ADD_CODE(&td
, MINT_CONV_U4_I8
);
1641 g_assert_not_reached ();
1644 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I
);
1647 CHECK_STACK (&td
, 1);
1648 switch (td
.sp
[-1].type
) {
1650 #if SIZEOF_VOID_P == 8
1651 ADD_CODE(&td
, MINT_CONV_I8_R8
);
1653 ADD_CODE(&td
, MINT_CONV_I4_R8
);
1657 #if SIZEOF_VOID_P == 8
1658 ADD_CODE(&td
, MINT_CONV_I8_I4
);
1666 #if SIZEOF_VOID_P == 4
1667 ADD_CODE(&td
, MINT_CONV_I4_I8
);
1671 g_assert_not_reached ();
1674 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I
);
1677 CHECK_STACK (&td
, 1);
1678 switch (td
.sp
[-1].type
) {
1680 ADD_CODE(&td
, MINT_CONV_U4_R8
);
1685 ADD_CODE(&td
, MINT_CONV_U4_I8
);
1688 #if SIZEOF_VOID_P == 8
1689 ADD_CODE(&td
, MINT_CONV_U4_I8
);
1693 g_assert_not_reached ();
1696 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1699 CHECK_STACK (&td
, 1);
1700 switch (td
.sp
[-1].type
) {
1702 ADD_CODE(&td
, MINT_CONV_I4_R8
);
1707 ADD_CODE(&td
, MINT_CONV_I4_I8
);
1710 #if SIZEOF_VOID_P == 8
1711 ADD_CODE(&td
, MINT_CONV_I4_I8
);
1715 g_assert_not_reached ();
1718 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1721 CHECK_STACK (&td
, 1);
1722 switch (td
.sp
[-1].type
) {
1724 ADD_CODE(&td
, MINT_CONV_I8_R8
);
1727 ADD_CODE(&td
, MINT_CONV_I8_I4
);
1732 #if SIZEOF_VOID_P == 4
1733 ADD_CODE(&td
, MINT_CONV_I8_I4
);
1737 g_assert_not_reached ();
1740 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
1743 CHECK_STACK (&td
, 1);
1744 switch (td
.sp
[-1].type
) {
1746 ADD_CODE(&td
, MINT_CONV_R4_R8
);
1749 ADD_CODE(&td
, MINT_CONV_R4_I8
);
1752 ADD_CODE(&td
, MINT_CONV_R4_I4
);
1755 g_assert_not_reached ();
1758 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
1761 CHECK_STACK (&td
, 1);
1762 switch (td
.sp
[-1].type
) {
1764 ADD_CODE(&td
, MINT_CONV_R8_I4
);
1767 ADD_CODE(&td
, MINT_CONV_R8_I8
);
1772 g_assert_not_reached ();
1775 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
1778 CHECK_STACK (&td
, 1);
1779 switch (td
.sp
[-1].type
) {
1781 ADD_CODE(&td
, MINT_CONV_U8_I4
);
1786 ADD_CODE(&td
, MINT_CONV_U8_R8
);
1789 #if SIZEOF_VOID_P == 4
1790 ADD_CODE(&td
, MINT_CONV_U8_I4
);
1794 g_assert_not_reached ();
1797 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
1800 CHECK_STACK (&td
, 2);
1802 token
= read32 (td
.ip
+ 1);
1803 klass
= mono_class_get_full (image
, token
, generic_context
);
1805 if (klass
->valuetype
) {
1806 ADD_CODE (&td
, MINT_CPOBJ
);
1807 ADD_CODE (&td
, get_data_item_index(&td
, klass
));
1809 ADD_CODE (&td
, MINT_LDIND_REF
);
1810 ADD_CODE (&td
, MINT_STIND_REF
);
1818 CHECK_STACK (&td
, 1);
1820 token
= read32 (td
.ip
+ 1);
1822 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
1823 klass
= (MonoClass
*)mono_method_get_wrapper_data (method
, token
);
1825 klass
= mono_class_get_full (image
, token
, generic_context
);
1827 ADD_CODE(&td
, MINT_LDOBJ
);
1828 ADD_CODE(&td
, get_data_item_index(&td
, klass
));
1829 if (mint_type (&klass
->byval_arg
) == MINT_TYPE_VT
) {
1830 size
= mono_class_value_size (klass
, NULL
);
1834 SET_TYPE(td
.sp
- 1, stack_type
[mint_type(&klass
->byval_arg
)], klass
);
1839 token
= mono_metadata_token_index (read32 (td
.ip
+ 1));
1841 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
) {
1842 s
= mono_string_new_wrapper(
1843 mono_method_get_wrapper_data (method
, token
));
1846 s
= mono_ldstr (domain
, image
, token
);
1847 ADD_CODE(&td
, MINT_LDSTR
);
1848 ADD_CODE(&td
, get_data_item_index (&td
, s
));
1849 PUSH_TYPE(&td
, STACK_TYPE_O
, mono_defaults
.string_class
);
1854 MonoMethodSignature
*csignature
;
1855 guint32 vt_stack_used
= 0;
1856 guint32 vt_res_size
= 0;
1859 token
= read32 (td
.ip
);
1862 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
1863 m
= (MonoMethod
*)mono_method_get_wrapper_data (method
, token
);
1865 m
= mono_get_method_full (image
, token
, NULL
, generic_context
);
1867 csignature
= mono_method_signature (m
);
1869 td
.sp
-= csignature
->param_count
;
1870 ADD_CODE(&td
, MINT_NEWOBJ
);
1871 ADD_CODE(&td
, get_data_item_index (&td
, mono_interp_get_runtime_method (domain
, m
, &error
)));
1872 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
1874 if (mint_type (&klass
->byval_arg
) == MINT_TYPE_VT
) {
1875 vt_res_size
= mono_class_value_size (klass
, NULL
);
1876 PUSH_VT (&td
, vt_res_size
);
1878 for (i
= 0; i
< csignature
->param_count
; ++i
) {
1879 int mt
= mint_type(csignature
->params
[i
]);
1880 if (mt
== MINT_TYPE_VT
) {
1881 MonoClass
*k
= mono_class_from_mono_type (csignature
->params
[i
]);
1882 gint32 size
= mono_class_value_size (k
, NULL
);
1883 size
= (size
+ 7) & ~7;
1884 vt_stack_used
+= size
;
1887 if (vt_stack_used
!= 0 || vt_res_size
!= 0) {
1888 ADD_CODE(&td
, MINT_VTRESULT
);
1889 ADD_CODE(&td
, vt_res_size
);
1890 WRITE32(&td
, &vt_stack_used
);
1891 td
.vt_sp
-= vt_stack_used
;
1893 PUSH_TYPE (&td
, stack_type
[mint_type (&klass
->byval_arg
)], klass
);
1897 CHECK_STACK (&td
, 1);
1898 token
= read32 (td
.ip
+ 1);
1899 klass
= mono_class_get_full (image
, token
, generic_context
);
1900 ADD_CODE(&td
, MINT_CASTCLASS
);
1901 ADD_CODE(&td
, get_data_item_index (&td
, klass
));
1902 td
.sp
[-1].klass
= klass
;
1906 CHECK_STACK (&td
, 1);
1907 token
= read32 (td
.ip
+ 1);
1908 klass
= mono_class_get_full (image
, token
, generic_context
);
1909 ADD_CODE(&td
, MINT_ISINST
);
1910 ADD_CODE(&td
, get_data_item_index (&td
, klass
));
1914 switch (td
.sp
[-1].type
) {
1918 ADD_CODE(&td
, MINT_CONV_R_UN_I8
);
1921 ADD_CODE(&td
, MINT_CONV_R_UN_I4
);
1924 g_assert_not_reached ();
1926 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
1930 CHECK_STACK (&td
, 1);
1931 token
= read32 (td
.ip
+ 1);
1933 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
1934 klass
= (MonoClass
*)mono_method_get_wrapper_data (method
, token
);
1936 klass
= mono_class_get_full (image
, token
, generic_context
);
1938 if (mono_class_is_nullable (klass
)) {
1939 g_error ("cee_unbox: implement Nullable");
1942 ADD_CODE(&td
, MINT_UNBOX
);
1943 ADD_CODE(&td
, get_data_item_index (&td
, klass
));
1944 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_MP
);
1948 CHECK_STACK (&td
, 1);
1949 token
= read32 (td
.ip
+ 1);
1951 g_assert (method
->wrapper_type
== MONO_WRAPPER_NONE
);
1952 klass
= mono_class_get_full (image
, token
, generic_context
);
1954 if (mini_type_is_reference (&klass
->byval_arg
)) {
1955 ADD_CODE (&td
, MINT_CASTCLASS
);
1956 ADD_CODE (&td
, get_data_item_index (&td
, klass
));
1957 SET_TYPE (td
.sp
- 1, stack_type
[mt
], klass
);
1959 } else if (mono_class_is_nullable (klass
)) {
1960 MonoMethod
*target_method
= mono_class_get_method_from_name (klass
, "Unbox", 1);
1961 /* td.ip is incremented by interp_transform_call */
1962 interp_transform_call (&td
, method
, target_method
, domain
, generic_context
, is_bb_start
, body_start_offset
, NULL
, FALSE
);
1964 int mt
= mint_type (&klass
->byval_arg
);
1965 ADD_CODE (&td
, MINT_UNBOX
);
1966 ADD_CODE (&td
, get_data_item_index (&td
, klass
));
1968 ADD_CODE (&td
, MINT_LDOBJ
);
1969 ADD_CODE (&td
, get_data_item_index(&td
, klass
));
1970 SET_TYPE (td
.sp
- 1, stack_type
[mt
], klass
);
1972 if (mt
== MINT_TYPE_VT
) {
1973 int size
= mono_class_value_size (klass
, NULL
);
1974 PUSH_VT (&td
, size
);
1981 CHECK_STACK (&td
, 1);
1982 SIMPLE_OP (td
, MINT_THROW
);
1984 generating_code
= 0;
1987 CHECK_STACK (&td
, 1);
1988 token
= read32 (td
.ip
+ 1);
1989 field
= mono_field_from_token (image
, token
, &klass
, generic_context
);
1990 gboolean is_static
= !!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
);
1991 mono_class_init (klass
);
1993 ADD_CODE (&td
, MINT_POP
);
1995 ADD_CODE (&td
, MINT_LDSFLDA
);
1996 ADD_CODE (&td
, get_data_item_index (&td
, field
));
1998 if ((td
.sp
- 1)->type
== STACK_TYPE_O
) {
1999 ADD_CODE (&td
, MINT_LDFLDA
);
2001 g_assert ((td
.sp
-1)->type
== STACK_TYPE_MP
);
2002 ADD_CODE (&td
, MINT_LDFLDA_UNSAFE
);
2004 ADD_CODE (&td
, klass
->valuetype
? field
->offset
- sizeof (MonoObject
) : field
->offset
);
2007 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_MP
);
2010 CHECK_STACK (&td
, 1);
2011 token
= read32 (td
.ip
+ 1);
2012 field
= mono_field_from_token (image
, token
, &klass
, generic_context
);
2013 gboolean is_static
= !!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
);
2014 mono_class_init (klass
);
2016 MonoClass
*field_klass
= mono_class_from_mono_type (field
->type
);
2017 mt
= mint_type (&field_klass
->byval_arg
);
2018 if (klass
->marshalbyref
) {
2019 g_assert (!is_static
);
2020 ADD_CODE(&td
, mt
== MINT_TYPE_VT
? MINT_LDRMFLD_VT
: MINT_LDRMFLD
);
2021 ADD_CODE(&td
, get_data_item_index (&td
, field
));
2024 ADD_CODE (&td
, MINT_POP
);
2026 ADD_CODE (&td
, mt
== MINT_TYPE_VT
? MINT_LDSFLD_VT
: MINT_LDSFLD
);
2027 ADD_CODE (&td
, get_data_item_index (&td
, field
));
2029 ADD_CODE (&td
, MINT_LDFLD_I1
+ mt
- MINT_TYPE_I1
);
2030 ADD_CODE (&td
, klass
->valuetype
? field
->offset
- sizeof(MonoObject
) : field
->offset
);
2033 if (mt
== MINT_TYPE_VT
) {
2034 int size
= mono_class_value_size (field_klass
, NULL
);
2036 WRITE32(&td
, &size
);
2038 if (td
.sp
[-1].type
== STACK_TYPE_VT
) {
2039 int size
= mono_class_value_size (klass
, NULL
);
2040 size
= (size
+ 7) & ~7;
2042 ADD_CODE (&td
, MINT_VTRESULT
);
2044 WRITE32 (&td
, &size
);
2047 SET_TYPE(td
.sp
- 1, stack_type
[mt
], field_klass
);
2051 CHECK_STACK (&td
, 2);
2052 token
= read32 (td
.ip
+ 1);
2053 field
= mono_field_from_token (image
, token
, &klass
, generic_context
);
2054 gboolean is_static
= !!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
);
2055 mono_class_init (klass
);
2056 mt
= mint_type(field
->type
);
2058 if (klass
->marshalbyref
) {
2059 g_assert (!is_static
);
2060 ADD_CODE(&td
, mt
== MINT_TYPE_VT
? MINT_STRMFLD_VT
: MINT_STRMFLD
);
2061 ADD_CODE(&td
, get_data_item_index (&td
, field
));
2064 ADD_CODE (&td
, MINT_POP
);
2066 ADD_CODE (&td
, mt
== MINT_TYPE_VT
? MINT_STSFLD_VT
: MINT_STSFLD
);
2067 ADD_CODE (&td
, get_data_item_index (&td
, field
));
2069 ADD_CODE (&td
, MINT_STFLD_I1
+ mt
- MINT_TYPE_I1
);
2070 ADD_CODE (&td
, klass
->valuetype
? field
->offset
- sizeof(MonoObject
) : field
->offset
);
2073 if (mt
== MINT_TYPE_VT
) {
2074 MonoClass
*klass
= mono_class_from_mono_type (field
->type
);
2075 int size
= mono_class_value_size (klass
, NULL
);
2077 WRITE32(&td
, &size
);
2084 token
= read32 (td
.ip
+ 1);
2085 field
= mono_field_from_token (image
, token
, &klass
, generic_context
);
2086 ADD_CODE(&td
, MINT_LDSFLDA
);
2087 ADD_CODE(&td
, get_data_item_index (&td
, field
));
2089 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_MP
);
2092 token
= read32 (td
.ip
+ 1);
2093 field
= mono_field_from_token (image
, token
, &klass
, generic_context
);
2094 mt
= mint_type(field
->type
);
2095 ADD_CODE(&td
, mt
== MINT_TYPE_VT
? MINT_LDSFLD_VT
: MINT_LDSFLD
);
2096 ADD_CODE(&td
, get_data_item_index (&td
, field
));
2098 if (mt
== MINT_TYPE_VT
) {
2099 MonoClass
*klass
= mono_class_from_mono_type (field
->type
);
2100 int size
= mono_class_value_size (klass
, NULL
);
2102 WRITE32(&td
, &size
);
2103 klass
= field
->type
->data
.klass
;
2105 if (mt
== MINT_TYPE_O
)
2106 klass
= mono_class_from_mono_type (field
->type
);
2109 PUSH_TYPE(&td
, stack_type
[mt
], klass
);
2112 CHECK_STACK (&td
, 1);
2113 token
= read32 (td
.ip
+ 1);
2114 field
= mono_field_from_token (image
, token
, &klass
, generic_context
);
2115 mt
= mint_type(field
->type
);
2116 ADD_CODE(&td
, mt
== MINT_TYPE_VT
? MINT_STSFLD_VT
: MINT_STSFLD
);
2117 ADD_CODE(&td
, get_data_item_index (&td
, field
));
2118 if (mt
== MINT_TYPE_VT
) {
2119 MonoClass
*klass
= mono_class_from_mono_type (field
->type
);
2120 int size
= mono_class_value_size (klass
, NULL
);
2122 WRITE32 (&td
, &size
);
2129 token
= read32 (td
.ip
+ 1);
2131 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
2132 klass
= (MonoClass
*)mono_method_get_wrapper_data (method
, token
);
2134 klass
= mono_class_get_full (image
, token
, generic_context
);
2136 ADD_CODE(&td
, td
.sp
[-1].type
== STACK_TYPE_VT
? MINT_STOBJ_VT
: MINT_STOBJ
);
2137 ADD_CODE(&td
, get_data_item_index (&td
, klass
));
2138 if (td
.sp
[-1].type
== STACK_TYPE_VT
) {
2139 size
= mono_class_value_size (klass
, NULL
);
2140 size
= (size
+ 7) & ~7;
2147 case CEE_CONV_OVF_I_UN
:
2148 case CEE_CONV_OVF_U_UN
:
2149 CHECK_STACK (&td
, 1);
2150 switch (td
.sp
[-1].type
) {
2152 #if SIZEOF_VOID_P == 8
2153 ADD_CODE(&td
, MINT_CONV_OVF_I8_UN_R8
);
2155 ADD_CODE(&td
, MINT_CONV_OVF_I4_UN_R8
);
2159 #if SIZEOF_VOID_P == 4
2160 ADD_CODE (&td
, MINT_CONV_OVF_I4_UN_I8
);
2164 #if SIZEOF_VOID_P == 8
2165 ADD_CODE(&td
, MINT_CONV_I8_U4
);
2169 g_assert_not_reached ();
2172 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
2175 case CEE_CONV_OVF_I8_UN
:
2176 case CEE_CONV_OVF_U8_UN
:
2177 CHECK_STACK (&td
, 1);
2178 switch (td
.sp
[-1].type
) {
2180 ADD_CODE(&td
, MINT_CONV_OVF_I8_UN_R8
);
2183 if (*td
.ip
== CEE_CONV_OVF_I8_UN
)
2184 ADD_CODE (&td
, MINT_CONV_OVF_I8_U8
);
2187 ADD_CODE(&td
, MINT_CONV_I8_U4
);
2190 g_assert_not_reached ();
2193 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
2198 CHECK_STACK (&td
, 1);
2199 token
= read32 (td
.ip
+ 1);
2200 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
2201 klass
= (MonoClass
*)mono_method_get_wrapper_data (method
, token
);
2203 klass
= mono_class_get_full (image
, token
, generic_context
);
2205 if (mono_class_is_nullable (klass
)) {
2206 MonoMethod
*target_method
= mono_class_get_method_from_name (klass
, "Box", 1);
2207 /* td.ip is incremented by interp_transform_call */
2208 interp_transform_call (&td
, method
, target_method
, domain
, generic_context
, is_bb_start
, body_start_offset
, NULL
, FALSE
);
2209 } else if (!klass
->valuetype
) {
2210 /* already boxed, do nothing. */
2213 if (mint_type (&klass
->byval_arg
) == MINT_TYPE_VT
&& !klass
->enumtype
) {
2214 size
= mono_class_value_size (klass
, NULL
);
2215 size
= (size
+ 7) & ~7;
2218 ADD_CODE(&td
, MINT_BOX
);
2219 ADD_CODE(&td
, get_data_item_index (&td
, klass
));
2221 SET_TYPE(td
.sp
- 1, STACK_TYPE_O
, klass
);
2228 CHECK_STACK (&td
, 1);
2229 token
= read32 (td
.ip
+ 1);
2231 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
2232 klass
= (MonoClass
*)mono_method_get_wrapper_data (method
, token
);
2234 klass
= mono_class_get_full (image
, token
, generic_context
);
2236 unsigned char lentype
= (td
.sp
- 1)->type
;
2237 if (lentype
== STACK_TYPE_I8
) {
2238 /* mimic mini behaviour */
2239 ADD_CODE (&td
, MINT_CONV_OVF_U4_I8
);
2241 g_assert (lentype
== STACK_TYPE_I4
);
2242 ADD_CODE (&td
, MINT_CONV_OVF_U4_I4
);
2244 SET_SIMPLE_TYPE (td
.sp
- 1, STACK_TYPE_I4
);
2245 ADD_CODE (&td
, MINT_NEWARR
);
2246 ADD_CODE (&td
, get_data_item_index (&td
, klass
));
2247 SET_TYPE (td
.sp
- 1, STACK_TYPE_O
, klass
);
2252 CHECK_STACK (&td
, 1);
2253 SIMPLE_OP (td
, MINT_LDLEN
);
2254 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I
);
2257 CHECK_STACK (&td
, 2);
2259 token
= read32 (td
.ip
+ 1);
2261 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
2262 klass
= (MonoClass
*) mono_method_get_wrapper_data (method
, token
);
2264 klass
= mono_class_get_full (image
, token
, generic_context
);
2266 if (!klass
->valuetype
&& method
->wrapper_type
== MONO_WRAPPER_NONE
&& !readonly
) {
2267 ADD_CODE (&td
, MINT_LDELEMA_TC
);
2269 ADD_CODE (&td
, MINT_LDELEMA
);
2271 ADD_CODE (&td
, get_data_item_index (&td
, klass
));
2272 /* according to spec, ldelema bytecode is only used for 1-dim arrays */
2278 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_MP
);
2281 CHECK_STACK (&td
, 2);
2283 SIMPLE_OP (td
, MINT_LDELEM_I1
);
2285 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2288 CHECK_STACK (&td
, 2);
2290 SIMPLE_OP (td
, MINT_LDELEM_U1
);
2292 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2295 CHECK_STACK (&td
, 2);
2297 SIMPLE_OP (td
, MINT_LDELEM_I2
);
2299 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2302 CHECK_STACK (&td
, 2);
2304 SIMPLE_OP (td
, MINT_LDELEM_U2
);
2306 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2309 CHECK_STACK (&td
, 2);
2311 SIMPLE_OP (td
, MINT_LDELEM_I4
);
2313 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2316 CHECK_STACK (&td
, 2);
2318 SIMPLE_OP (td
, MINT_LDELEM_U4
);
2320 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2323 CHECK_STACK (&td
, 2);
2325 SIMPLE_OP (td
, MINT_LDELEM_I8
);
2327 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
2330 CHECK_STACK (&td
, 2);
2332 SIMPLE_OP (td
, MINT_LDELEM_I
);
2334 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I
);
2337 CHECK_STACK (&td
, 2);
2339 SIMPLE_OP (td
, MINT_LDELEM_R4
);
2341 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
2344 CHECK_STACK (&td
, 2);
2346 SIMPLE_OP (td
, MINT_LDELEM_R8
);
2348 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
2350 case CEE_LDELEM_REF
:
2351 CHECK_STACK (&td
, 2);
2353 SIMPLE_OP (td
, MINT_LDELEM_REF
);
2355 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_O
);
2358 CHECK_STACK (&td
, 2);
2359 token
= read32 (td
.ip
+ 1);
2360 klass
= mono_class_get_full (image
, token
, generic_context
);
2361 switch (mint_type (&klass
->byval_arg
)) {
2364 SIMPLE_OP (td
, MINT_LDELEM_I1
);
2366 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2370 SIMPLE_OP (td
, MINT_LDELEM_U1
);
2372 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2376 SIMPLE_OP (td
, MINT_LDELEM_U2
);
2378 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2382 SIMPLE_OP (td
, MINT_LDELEM_I2
);
2384 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2388 SIMPLE_OP (td
, MINT_LDELEM_I4
);
2390 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2394 SIMPLE_OP (td
, MINT_LDELEM_I8
);
2396 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
2400 SIMPLE_OP (td
, MINT_LDELEM_R4
);
2402 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
2406 SIMPLE_OP (td
, MINT_LDELEM_R8
);
2408 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
2412 SIMPLE_OP (td
, MINT_LDELEM_REF
);
2414 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_O
);
2416 case MINT_TYPE_VT
: {
2417 int size
= mono_class_value_size (klass
, NULL
);
2419 SIMPLE_OP (td
, MINT_LDELEM_VT
);
2420 ADD_CODE (&td
, get_data_item_index (&td
, klass
));
2421 WRITE32 (&td
, &size
);
2423 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_VT
);
2424 PUSH_VT (&td
, size
);
2428 GString
*res
= g_string_new ("");
2429 mono_type_get_desc (res
, &klass
->byval_arg
, TRUE
);
2430 g_print ("LDELEM: %s -> %d (%s)\n", klass
->name
, mint_type (&klass
->byval_arg
), res
->str
);
2431 g_string_free (res
, TRUE
);
2439 CHECK_STACK (&td
, 3);
2441 SIMPLE_OP (td
, MINT_STELEM_I
);
2445 CHECK_STACK (&td
, 3);
2447 SIMPLE_OP (td
, MINT_STELEM_I1
);
2451 CHECK_STACK (&td
, 3);
2453 SIMPLE_OP (td
, MINT_STELEM_I2
);
2457 CHECK_STACK (&td
, 3);
2459 SIMPLE_OP (td
, MINT_STELEM_I4
);
2463 CHECK_STACK (&td
, 3);
2465 SIMPLE_OP (td
, MINT_STELEM_I8
);
2469 CHECK_STACK (&td
, 3);
2471 SIMPLE_OP (td
, MINT_STELEM_R4
);
2475 CHECK_STACK (&td
, 3);
2477 SIMPLE_OP (td
, MINT_STELEM_R8
);
2480 case CEE_STELEM_REF
:
2481 CHECK_STACK (&td
, 3);
2483 SIMPLE_OP (td
, MINT_STELEM_REF
);
2487 CHECK_STACK (&td
, 3);
2489 token
= read32 (td
.ip
+ 1);
2490 klass
= mono_class_get_full (image
, token
, generic_context
);
2491 switch (mint_type (&klass
->byval_arg
)) {
2493 SIMPLE_OP (td
, MINT_STELEM_U1
);
2496 SIMPLE_OP (td
, MINT_STELEM_I4
);
2499 SIMPLE_OP (td
, MINT_STELEM_REF
);
2501 case MINT_TYPE_VT
: {
2502 int size
= mono_class_value_size (klass
, NULL
);
2503 SIMPLE_OP (td
, MINT_STELEM_VT
);
2504 ADD_CODE (&td
, get_data_item_index (&td
, klass
));
2505 WRITE32 (&td
, &size
);
2510 GString
*res
= g_string_new ("");
2511 mono_type_get_desc (res
, &klass
->byval_arg
, TRUE
);
2512 g_print ("STELEM: %s -> %d (%s)\n", klass
->name
, mint_type (&klass
->byval_arg
), res
->str
);
2513 g_string_free (res
, TRUE
);
2522 case CEE_CONV_OVF_U1
:
2524 case CEE_CONV_OVF_I8
:
2526 #if SIZEOF_VOID_P == 8
2527 case CEE_CONV_OVF_U
:
2529 case CEE_REFANYVAL
: ves_abort(); break;
2532 CHECK_STACK (&td
, 1);
2533 SIMPLE_OP (td
, MINT_CKFINITE
);
2535 case CEE_CONV_OVF_I1
:
2536 case CEE_CONV_OVF_I1_UN
:
2537 CHECK_STACK (&td
, 1);
2538 switch (td
.sp
[-1].type
) {
2540 ADD_CODE(&td
, MINT_CONV_OVF_I1_R8
);
2543 ADD_CODE(&td
, MINT_CONV_OVF_I1_I4
);
2546 ADD_CODE(&td
, MINT_CONV_OVF_I1_I8
);
2549 g_assert_not_reached ();
2552 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2554 case CEE_CONV_OVF_U1
:
2555 case CEE_CONV_OVF_U1_UN
:
2556 CHECK_STACK (&td
, 1);
2557 switch (td
.sp
[-1].type
) {
2559 ADD_CODE(&td
, MINT_CONV_OVF_U1_R8
);
2562 ADD_CODE(&td
, MINT_CONV_OVF_U1_I4
);
2565 ADD_CODE(&td
, MINT_CONV_OVF_U1_I8
);
2568 g_assert_not_reached ();
2571 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2573 case CEE_CONV_OVF_I2
:
2574 case CEE_CONV_OVF_I2_UN
:
2575 CHECK_STACK (&td
, 1);
2576 switch (td
.sp
[-1].type
) {
2578 ADD_CODE(&td
, MINT_CONV_OVF_I2_R8
);
2581 ADD_CODE(&td
, MINT_CONV_OVF_I2_I4
);
2584 ADD_CODE(&td
, MINT_CONV_OVF_I2_I8
);
2587 g_assert_not_reached ();
2590 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2592 case CEE_CONV_OVF_U2_UN
:
2593 case CEE_CONV_OVF_U2
:
2594 CHECK_STACK (&td
, 1);
2595 switch (td
.sp
[-1].type
) {
2597 ADD_CODE(&td
, MINT_CONV_OVF_U2_R8
);
2600 ADD_CODE(&td
, MINT_CONV_OVF_U2_I4
);
2603 ADD_CODE(&td
, MINT_CONV_OVF_U2_I8
);
2606 g_assert_not_reached ();
2609 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2611 #if SIZEOF_VOID_P == 4
2612 case CEE_CONV_OVF_I
:
2614 case CEE_CONV_OVF_I4
:
2615 case CEE_CONV_OVF_I4_UN
:
2616 CHECK_STACK (&td
, 1);
2617 switch (td
.sp
[-1].type
) {
2619 ADD_CODE(&td
, MINT_CONV_OVF_I4_R8
);
2622 if (*td
.ip
== CEE_CONV_OVF_I4_UN
)
2623 ADD_CODE(&td
, MINT_CONV_OVF_I4_U4
);
2626 if (*td
.ip
== CEE_CONV_OVF_I4_UN
)
2627 ADD_CODE (&td
, MINT_CONV_OVF_I4_U8
);
2629 ADD_CODE (&td
, MINT_CONV_OVF_I4_I8
);
2632 g_assert_not_reached ();
2635 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2637 #if SIZEOF_VOID_P == 4
2638 case CEE_CONV_OVF_U
:
2640 case CEE_CONV_OVF_U4
:
2641 case CEE_CONV_OVF_U4_UN
:
2642 CHECK_STACK (&td
, 1);
2643 switch (td
.sp
[-1].type
) {
2645 ADD_CODE(&td
, MINT_CONV_OVF_U4_R8
);
2648 if (*td
.ip
!= CEE_CONV_OVF_U4_UN
)
2649 ADD_CODE(&td
, MINT_CONV_OVF_U4_I4
);
2652 ADD_CODE(&td
, MINT_CONV_OVF_U4_I8
);
2655 g_assert_not_reached ();
2658 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2660 #if SIZEOF_VOID_P == 8
2661 case CEE_CONV_OVF_I
:
2663 case CEE_CONV_OVF_I8
:
2664 CHECK_STACK (&td
, 1);
2665 switch (td
.sp
[-1].type
) {
2667 ADD_CODE(&td
, MINT_CONV_OVF_I8_R8
);
2670 ADD_CODE(&td
, MINT_CONV_I8_I4
);
2675 g_assert_not_reached ();
2678 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
2680 #if SIZEOF_VOID_P == 8
2681 case CEE_CONV_OVF_U
:
2683 case CEE_CONV_OVF_U8
:
2684 CHECK_STACK (&td
, 1);
2685 switch (td
.sp
[-1].type
) {
2687 ADD_CODE(&td
, MINT_CONV_OVF_U8_R8
);
2690 ADD_CODE(&td
, MINT_CONV_OVF_U8_I4
);
2693 ADD_CODE (&td
, MINT_CONV_OVF_U8_I8
);
2696 g_assert_not_reached ();
2699 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
2704 token
= read32 (td
.ip
+ 1);
2705 if (method
->wrapper_type
== MONO_WRAPPER_DYNAMIC_METHOD
|| method
->wrapper_type
== MONO_WRAPPER_SYNCHRONIZED
) {
2706 handle
= mono_method_get_wrapper_data (method
, token
);
2707 klass
= (MonoClass
*) mono_method_get_wrapper_data (method
, token
+ 1);
2708 if (klass
== mono_defaults
.typehandle_class
)
2709 handle
= &((MonoClass
*) handle
)->byval_arg
;
2711 handle
= mono_ldtoken (image
, token
, &klass
, generic_context
);
2713 mt
= mint_type (&klass
->byval_arg
);
2714 g_assert (mt
== MINT_TYPE_VT
);
2715 size
= mono_class_value_size (klass
, NULL
);
2716 g_assert (size
== sizeof(gpointer
));
2717 PUSH_VT (&td
, sizeof(gpointer
));
2718 ADD_CODE (&td
, MINT_LDTOKEN
);
2719 ADD_CODE (&td
, get_data_item_index (&td
, handle
));
2721 SET_TYPE (td
.sp
, stack_type
[mt
], klass
);
2727 binary_arith_op(&td
, MINT_ADD_OVF_I4
);
2730 case CEE_ADD_OVF_UN
:
2731 binary_arith_op(&td
, MINT_ADD_OVF_UN_I4
);
2735 binary_arith_op(&td
, MINT_MUL_OVF_I4
);
2738 case CEE_MUL_OVF_UN
:
2739 binary_arith_op(&td
, MINT_MUL_OVF_UN_I4
);
2743 binary_arith_op(&td
, MINT_SUB_OVF_I4
);
2746 case CEE_SUB_OVF_UN
:
2747 binary_arith_op(&td
, MINT_SUB_OVF_UN_I4
);
2750 case CEE_ENDFINALLY
:
2751 SIMPLE_OP (td
, MINT_ENDFINALLY
);
2752 generating_code
= 0;
2756 handle_branch (&td
, MINT_LEAVE_S
, MINT_LEAVE
, 5 + read32 (td
.ip
+ 1));
2758 generating_code
= 0;
2762 handle_branch (&td
, MINT_LEAVE_S
, MINT_LEAVE
, 2 + (gint8
)td
.ip
[1]);
2764 generating_code
= 0;
2769 case CEE_MONO_CALLI_EXTRA_ARG
:
2770 /* Same as CEE_CALLI, except that we drop the extra arg required for llvm specific behaviour */
2771 ADD_CODE (&td
, MINT_POP
);
2774 interp_transform_call (&td
, method
, NULL
, domain
, generic_context
, is_bb_start
, body_start_offset
, NULL
, FALSE
);
2776 case CEE_MONO_JIT_ICALL_ADDR
: {
2779 MonoJitICallInfo
*info
;
2781 token
= read32 (td
.ip
+ 1);
2783 func
= mono_method_get_wrapper_data (method
, token
);
2784 info
= mono_find_jit_icall_by_addr (func
);
2786 ADD_CODE (&td
, MINT_LDFTN
);
2787 ADD_CODE (&td
, get_data_item_index (&td
, func
));
2788 PUSH_SIMPLE_TYPE (&td
, STACK_TYPE_I
);
2791 case CEE_MONO_ICALL
: {
2794 MonoJitICallInfo
*info
;
2796 token
= read32 (td
.ip
+ 1);
2798 func
= mono_method_get_wrapper_data (method
, token
);
2799 info
= mono_find_jit_icall_by_addr (func
);
2802 CHECK_STACK (&td
, info
->sig
->param_count
);
2803 switch (info
->sig
->param_count
) {
2805 if (MONO_TYPE_IS_VOID (info
->sig
->ret
))
2806 ADD_CODE (&td
,MINT_ICALL_V_V
);
2808 ADD_CODE (&td
, MINT_ICALL_V_P
);
2811 if (MONO_TYPE_IS_VOID (info
->sig
->ret
))
2812 ADD_CODE (&td
,MINT_ICALL_P_V
);
2814 ADD_CODE (&td
,MINT_ICALL_P_P
);
2817 if (MONO_TYPE_IS_VOID (info
->sig
->ret
)) {
2818 if (info
->sig
->params
[1]->type
== MONO_TYPE_I4
)
2819 ADD_CODE (&td
,MINT_ICALL_PI_V
);
2821 ADD_CODE (&td
,MINT_ICALL_PP_V
);
2823 if (info
->sig
->params
[1]->type
== MONO_TYPE_I4
)
2824 ADD_CODE (&td
,MINT_ICALL_PI_P
);
2826 ADD_CODE (&td
,MINT_ICALL_PP_P
);
2830 g_assert (MONO_TYPE_IS_VOID (info
->sig
->ret
));
2831 if (info
->sig
->params
[2]->type
== MONO_TYPE_I4
)
2832 ADD_CODE (&td
,MINT_ICALL_PPI_V
);
2834 ADD_CODE (&td
,MINT_ICALL_PPP_V
);
2837 g_assert_not_reached ();
2840 if (func
== mono_ftnptr_to_delegate
) {
2841 g_error ("TODO: ?");
2843 ADD_CODE(&td
, get_data_item_index (&td
, func
));
2844 td
.sp
-= info
->sig
->param_count
;
2846 if (!MONO_TYPE_IS_VOID (info
->sig
->ret
)) {
2848 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I
);
2852 case CEE_MONO_VTADDR
: {
2854 CHECK_STACK (&td
, 1);
2855 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
)
2856 size
= mono_class_native_size(td
.sp
[-1].klass
, NULL
);
2858 size
= mono_class_value_size(td
.sp
[-1].klass
, NULL
);
2859 size
= (size
+ 7) & ~7;
2860 ADD_CODE(&td
, MINT_VTRESULT
);
2862 WRITE32(&td
, &size
);
2865 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_MP
);
2868 case CEE_MONO_LDPTR
:
2869 case CEE_MONO_CLASSCONST
:
2870 token
= read32 (td
.ip
+ 1);
2872 ADD_CODE(&td
, MINT_MONO_LDPTR
);
2873 ADD_CODE(&td
, get_data_item_index (&td
, mono_method_get_wrapper_data (method
, token
)));
2874 td
.sp
[0].type
= STACK_TYPE_I
;
2877 case CEE_MONO_OBJADDR
:
2878 CHECK_STACK (&td
, 1);
2880 td
.sp
[-1].type
= STACK_TYPE_MP
;
2883 case CEE_MONO_NEWOBJ
:
2884 token
= read32 (td
.ip
+ 1);
2886 ADD_CODE(&td
, MINT_MONO_NEWOBJ
);
2887 ADD_CODE(&td
, get_data_item_index (&td
, mono_method_get_wrapper_data (method
, token
)));
2888 td
.sp
[0].type
= STACK_TYPE_O
;
2891 case CEE_MONO_RETOBJ
:
2892 CHECK_STACK (&td
, 1);
2893 token
= read32 (td
.ip
+ 1);
2895 ADD_CODE(&td
, MINT_MONO_RETOBJ
);
2898 klass
= (MonoClass
*)mono_method_get_wrapper_data (method
, token
);
2900 /*stackval_from_data (signature->ret, frame->retval, sp->data.vt, signature->pinvoke);*/
2902 if (td
.sp
> td
.stack
)
2903 g_warning ("CEE_MONO_RETOBJ: more values on stack: %d", td
.sp
-td
.stack
);
2905 case CEE_MONO_LDNATIVEOBJ
:
2906 token
= read32 (td
.ip
+ 1);
2908 klass
= (MonoClass
*)mono_method_get_wrapper_data (method
, token
);
2909 g_assert(klass
->valuetype
);
2910 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_MP
);
2912 case CEE_MONO_SAVE_LMF
:
2913 case CEE_MONO_RESTORE_LMF
:
2914 case CEE_MONO_NOT_TAKEN
:
2917 case CEE_MONO_LDPTR_INT_REQ_FLAG
:
2918 ADD_CODE (&td
, MINT_MONO_LDPTR
);
2919 ADD_CODE (&td
, get_data_item_index (&td
, mono_thread_interruption_request_flag ()));
2920 PUSH_TYPE (&td
, STACK_TYPE_MP
, NULL
);
2924 g_error ("transform.c: Unimplemented opcode: 0xF0 %02x at 0x%x\n", *td
.ip
, td
.ip
-header
->code
);
2934 case CEE_PREFIXREF
: ves_abort(); break;
2937 * Note: Exceptions thrown when executing a prefixed opcode need
2938 * to take into account the number of prefix bytes (usually the
2939 * throw point is just (ip - n_prefix_bytes).
2945 case CEE_ARGLIST
: ves_abort(); break;
2948 CHECK_STACK(&td
, 2);
2949 if (td
.sp
[-1].type
== STACK_TYPE_O
|| td
.sp
[-1].type
== STACK_TYPE_MP
)
2950 ADD_CODE(&td
, MINT_CEQ_I4
+ STACK_TYPE_I
- STACK_TYPE_I4
);
2952 ADD_CODE(&td
, MINT_CEQ_I4
+ td
.sp
[-1].type
- STACK_TYPE_I4
);
2954 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2958 CHECK_STACK(&td
, 2);
2959 if (td
.sp
[-1].type
== STACK_TYPE_O
|| td
.sp
[-1].type
== STACK_TYPE_MP
)
2960 ADD_CODE(&td
, MINT_CGT_I4
+ STACK_TYPE_I
- STACK_TYPE_I4
);
2962 ADD_CODE(&td
, MINT_CGT_I4
+ td
.sp
[-1].type
- STACK_TYPE_I4
);
2964 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2968 CHECK_STACK(&td
, 2);
2969 if (td
.sp
[-1].type
== STACK_TYPE_O
|| td
.sp
[-1].type
== STACK_TYPE_MP
)
2970 ADD_CODE(&td
, MINT_CGT_UN_I4
+ STACK_TYPE_I
- STACK_TYPE_I4
);
2972 ADD_CODE(&td
, MINT_CGT_UN_I4
+ td
.sp
[-1].type
- STACK_TYPE_I4
);
2974 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2978 CHECK_STACK(&td
, 2);
2979 if (td
.sp
[-1].type
== STACK_TYPE_O
|| td
.sp
[-1].type
== STACK_TYPE_MP
)
2980 ADD_CODE(&td
, MINT_CLT_I4
+ STACK_TYPE_I
- STACK_TYPE_I4
);
2982 ADD_CODE(&td
, MINT_CLT_I4
+ td
.sp
[-1].type
- STACK_TYPE_I4
);
2984 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2988 CHECK_STACK(&td
, 2);
2989 if (td
.sp
[-1].type
== STACK_TYPE_O
|| td
.sp
[-1].type
== STACK_TYPE_MP
)
2990 ADD_CODE(&td
, MINT_CLT_UN_I4
+ STACK_TYPE_I
- STACK_TYPE_I4
);
2992 ADD_CODE(&td
, MINT_CLT_UN_I4
+ td
.sp
[-1].type
- STACK_TYPE_I4
);
2994 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2997 case CEE_LDVIRTFTN
: /* fallthrough */
3000 if (*td
.ip
== CEE_LDVIRTFTN
) {
3001 CHECK_STACK (&td
, 1);
3004 token
= read32 (td
.ip
+ 1);
3005 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
3006 m
= (MonoMethod
*)mono_method_get_wrapper_data (method
, token
);
3008 m
= mono_get_method_full (image
, token
, NULL
, generic_context
);
3010 if (method
->wrapper_type
== MONO_WRAPPER_NONE
&& m
->iflags
& METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED
)
3011 m
= mono_marshal_get_synchronized_wrapper (m
);
3013 ADD_CODE(&td
, *td
.ip
== CEE_LDFTN
? MINT_LDFTN
: MINT_LDVIRTFTN
);
3014 ADD_CODE(&td
, get_data_item_index (&td
, mono_interp_get_runtime_method (domain
, m
, &error
)));
3015 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
3017 PUSH_SIMPLE_TYPE (&td
, STACK_TYPE_F
);
3021 load_arg (&td
, read16 (td
.ip
+ 1));
3025 int n
= read16 (td
.ip
+ 1);
3026 if (n
== 0 && signature
->hasthis
) {
3027 g_error ("LDTHISA: NOPE");
3028 ADD_CODE(&td
, MINT_LDTHISA
);
3031 ADD_CODE(&td
, MINT_LDARGA
);
3032 ADD_CODE(&td
, td
.rtm
->arg_offsets
[n
]); /* FIX for large offsets */
3034 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_MP
);
3039 store_arg (&td
, read16 (td
.ip
+ 1));
3043 load_local (&td
, read16 (td
.ip
+ 1));
3047 ADD_CODE(&td
, MINT_LDLOCA_S
);
3048 ADD_CODE(&td
, td
.rtm
->local_offsets
[read16 (td
.ip
+ 1)]);
3049 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_MP
);
3053 store_local (&td
, read16 (td
.ip
+ 1));
3057 CHECK_STACK (&td
, 1);
3058 #if SIZEOF_VOID_P == 8
3059 if (td
.sp
[-1].type
== STACK_TYPE_I8
)
3060 ADD_CODE(&td
, MINT_CONV_I4_I8
);
3062 ADD_CODE(&td
, MINT_LOCALLOC
);
3063 if (td
.sp
!= td
.stack
+ 1)
3064 g_warning("CEE_LOCALLOC: stack not empty");
3066 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_MP
);
3069 case CEE_UNUSED57
: ves_abort(); break;
3070 case CEE_ENDFILTER
: ves_abort(); break;
3072 case CEE_UNALIGNED_
:
3074 /* FIX: should do something? */;
3078 /* FIX: should do something? */;
3082 /* FIX: should do something? */;
3085 CHECK_STACK(&td
, 1);
3086 token
= read32 (td
.ip
+ 1);
3087 klass
= mono_class_get_full (image
, token
, generic_context
);
3088 if (klass
->valuetype
) {
3089 ADD_CODE (&td
, MINT_INITOBJ
);
3090 i32
= mono_class_value_size (klass
, NULL
);
3091 WRITE32 (&td
, &i32
);
3093 ADD_CODE (&td
, MINT_LDNULL
);
3094 ADD_CODE (&td
, MINT_STIND_REF
);
3100 CHECK_STACK(&td
, 3);
3101 /* FIX? convert length to I8? */
3102 ADD_CODE(&td
, MINT_CPBLK
);
3110 case CEE_CONSTRAINED_
:
3111 token
= read32 (td
.ip
+ 1);
3112 constrained_class
= mono_class_get_full (image
, token
, generic_context
);
3113 mono_class_init (constrained_class
);
3117 CHECK_STACK(&td
, 3);
3118 ADD_CODE(&td
, MINT_INITBLK
);
3123 /* FIXME: implement */
3128 SIMPLE_OP (td
, MINT_RETHROW
);
3129 generating_code
= 0;
3133 token
= read32 (td
.ip
+ 1);
3135 if (mono_metadata_token_table (token
) == MONO_TABLE_TYPESPEC
&& !image_is_dynamic (method
->klass
->image
) && !generic_context
) {
3137 MonoType
*type
= mono_type_create_from_typespec (image
, token
);
3138 size
= mono_type_size (type
, &align
);
3141 MonoClass
*szclass
= mono_class_get_full (image
, token
, generic_context
);
3142 mono_class_init (szclass
);
3144 if (!szclass
->valuetype
)
3145 THROW_EX (mono_exception_from_name (mono_defaults
.corlib
, "System", "InvalidProgramException"), ip
- 5);
3147 size
= mono_type_size (&szclass
->byval_arg
, &align
);
3149 ADD_CODE(&td
, MINT_LDC_I4
);
3150 WRITE32(&td
, &size
);
3151 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I4
);
3155 case CEE_REFANYTYPE
: ves_abort(); break;
3158 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
);
3162 g_error ("transform.c: Unimplemented opcode: %02x at 0x%x\n", *td
.ip
, td
.ip
-header
->code
);
3165 if (td
.new_ip
- td
.new_code
!= new_in_start_offset
)
3166 td
.last_new_ip
= td
.new_code
+ new_in_start_offset
;
3167 else if (td
.is_bb_start
[td
.in_start
- td
.il_code
])
3168 td
.is_bb_start
[td
.ip
- td
.il_code
] = 1;
3170 td
.last_ip
= td
.in_start
;
3173 if (mono_interp_traceopt
) {
3174 const guint16
*p
= td
.new_code
;
3175 printf("Runtime method: %p, VT stack size: %d\n", rtm
, td
.max_vt_sp
);
3176 printf("Calculated stack size: %d, stated size: %d\n", td
.max_stack_height
, header
->max_stack
);
3177 while (p
< td
.new_ip
) {
3178 p
= mono_interp_dis_mintop(td
.new_code
, p
);
3182 g_assert (td
.max_stack_height
<= (header
->max_stack
+ 1));
3184 rtm
->clauses
= mono_mempool_alloc (domain
->mp
, header
->num_clauses
* sizeof(MonoExceptionClause
));
3185 memcpy (rtm
->clauses
, header
->clauses
, header
->num_clauses
* sizeof(MonoExceptionClause
));
3186 rtm
->code
= mono_mempool_alloc (domain
->mp
, (td
.new_ip
- td
.new_code
) * sizeof(gushort
));
3187 memcpy (rtm
->code
, td
.new_code
, (td
.new_ip
- td
.new_code
) * sizeof(gushort
));
3188 g_free (td
.new_code
);
3189 rtm
->new_body_start
= rtm
->code
+ body_start_offset
;
3190 rtm
->num_clauses
= header
->num_clauses
;
3191 for (i
= 0; i
< header
->num_clauses
; i
++) {
3192 MonoExceptionClause
*c
= rtm
->clauses
+ i
;
3193 int end_off
= c
->try_offset
+ c
->try_len
;
3194 c
->try_offset
= td
.in_offsets
[c
->try_offset
];
3195 c
->try_len
= td
.in_offsets
[end_off
] - c
->try_offset
;
3196 end_off
= c
->handler_offset
+ c
->handler_len
;
3197 c
->handler_offset
= td
.in_offsets
[c
->handler_offset
];
3198 c
->handler_len
= td
.in_offsets
[end_off
] - c
->handler_offset
;
3200 rtm
->vt_stack_size
= td
.max_vt_sp
;
3201 rtm
->alloca_size
= rtm
->locals_size
+ rtm
->args_size
+ rtm
->vt_stack_size
+ rtm
->stack_size
;
3202 rtm
->data_items
= mono_mempool_alloc (domain
->mp
, td
.n_data_items
* sizeof (td
.data_items
[0]));
3203 memcpy (rtm
->data_items
, td
.data_items
, td
.n_data_items
* sizeof (td
.data_items
[0]));
3204 g_free (td
.in_offsets
);
3205 g_free (td
.forward_refs
);
3206 for (i
= 0; i
< header
->code_size
; ++i
)
3207 g_free (td
.stack_state
[i
]);
3208 g_free (td
.stack_state
);
3209 g_free (td
.stack_height
);
3210 g_free (td
.vt_stack_size
);
3211 g_free (td
.data_items
);
3213 g_hash_table_destroy (td
.data_hash
);
3216 static mono_mutex_t calc_section
;
3219 mono_interp_transform_init (void)
3221 mono_os_mutex_init_recursive(&calc_section
);
3225 mono_interp_transform_method (RuntimeMethod
*runtime_method
, ThreadContext
*context
)
3227 int i
, align
, size
, offset
;
3228 MonoMethod
*method
= runtime_method
->method
;
3229 MonoImage
*image
= method
->klass
->image
;
3230 MonoMethodHeader
*header
= mono_method_get_header (method
);
3231 MonoMethodSignature
*signature
= mono_method_signature (method
);
3232 register const unsigned char *ip
, *end
;
3233 const MonoOpcode
*opcode
;
3236 MonoDomain
*domain
= mono_domain_get ();
3237 unsigned char *is_bb_start
;
3239 MonoVTable
*method_class_vt
;
3241 MonoGenericContext
*generic_context
= NULL
;
3243 // g_printerr ("TRANSFORM(0x%016lx): begin %s::%s\n", mono_thread_current (), method->klass->name, method->name);
3244 method_class_vt
= mono_class_vtable (domain
, runtime_method
->method
->klass
);
3245 if (!method_class_vt
->initialized
) {
3247 MonoInvocation
*last_env_frame
= context
->env_frame
;
3248 jmp_buf *old_env
= context
->current_env
;
3251 MonoException
*failed
= context
->env_frame
->ex
;
3252 context
->env_frame
->ex
= NULL
;
3253 context
->env_frame
= last_env_frame
;
3254 context
->current_env
= old_env
;
3257 context
->env_frame
= context
->current_frame
;
3258 context
->current_env
= &env
;
3259 mono_runtime_class_init (method_class_vt
);
3260 context
->env_frame
= last_env_frame
;
3261 context
->current_env
= old_env
;
3264 mono_profiler_method_jit (method
); /* sort of... */
3266 if (mono_method_signature (method
)->is_inflated
)
3267 generic_context
= mono_method_get_context (method
);
3269 MonoGenericContainer
*generic_container
= mono_method_get_generic_container (method
);
3270 if (generic_container
)
3271 generic_context
= &generic_container
->context
;
3274 if (method
->iflags
& (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
| METHOD_IMPL_ATTRIBUTE_RUNTIME
)) {
3275 MonoMethod
*nm
= NULL
;
3276 mono_os_mutex_lock(&calc_section
);
3277 if (runtime_method
->transformed
) {
3278 mono_os_mutex_unlock(&calc_section
);
3279 g_error ("FIXME: no jit info?");
3280 mono_profiler_method_end_jit (method
, NULL
, MONO_PROFILE_OK
);
3284 /* assumes all internal calls with an array this are built in... */
3285 if (method
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
&& (! mono_method_signature (method
)->hasthis
|| method
->klass
->rank
== 0)) {
3286 nm
= mono_marshal_get_native_wrapper (method
, TRUE
, FALSE
);
3287 signature
= mono_method_signature (nm
);
3289 const char *name
= method
->name
;
3290 if (method
->klass
->parent
== mono_defaults
.multicastdelegate_class
) {
3291 if (*name
== '.' && (strcmp (name
, ".ctor") == 0)) {
3292 MonoJitICallInfo
*mi
= mono_find_jit_icall_by_name ("ves_icall_mono_delegate_ctor");
3294 char *wrapper_name
= g_strdup_printf ("__icall_wrapper_%s", mi
->name
);
3295 nm
= mono_marshal_get_icall_wrapper (mi
->sig
, wrapper_name
, mi
->func
, TRUE
);
3296 } else if (*name
== 'I' && (strcmp (name
, "Invoke") == 0)) {
3297 nm
= mono_marshal_get_delegate_invoke (method
, NULL
);
3298 } else if (*name
== 'B' && (strcmp (name
, "BeginInvoke") == 0)) {
3299 nm
= mono_marshal_get_delegate_begin_invoke (method
);
3300 } else if (*name
== 'E' && (strcmp (name
, "EndInvoke") == 0)) {
3301 nm
= mono_marshal_get_delegate_end_invoke (method
);
3305 runtime_method
->code
= g_malloc(sizeof(short));
3306 runtime_method
->code
[0] = MINT_CALLRUN
;
3310 runtime_method
->stack_size
= sizeof (stackval
); /* for tracing */
3311 runtime_method
->alloca_size
= runtime_method
->stack_size
;
3312 runtime_method
->transformed
= TRUE
;
3313 mono_os_mutex_unlock(&calc_section
);
3314 mono_profiler_method_end_jit (method
, NULL
, MONO_PROFILE_OK
);
3318 header
= mono_method_get_header (nm
);
3319 mono_os_mutex_unlock(&calc_section
);
3321 g_assert ((signature
->param_count
+ signature
->hasthis
) < 1000);
3322 g_assert (header
->max_stack
< 10000);
3323 /* intern the strings in the method. */
3325 end
= ip
+ header
->code_size
;
3327 is_bb_start
= g_malloc0(header
->code_size
);
3328 is_bb_start
[0] = 1;
3335 else if (in
== 0xf0) {
3337 in
= *ip
+ MONO_CEE_MONO_ICALL
;
3339 opcode
= &mono_opcodes
[in
];
3340 switch (opcode
->argument
) {
3341 case MonoInlineNone
:
3344 case MonoInlineString
:
3345 if (method
->wrapper_type
== MONO_WRAPPER_NONE
)
3346 mono_ldstr (domain
, image
, mono_metadata_token_index (read32 (ip
+ 1)));
3349 case MonoInlineType
:
3350 if (method
->wrapper_type
== MONO_WRAPPER_NONE
) {
3351 class = mono_class_get_full (image
, read32 (ip
+ 1), generic_context
);
3352 mono_class_init (class);
3353 /* quick fix to not do this for the fake ptr classes - probably should not be getting the vtable at all here */
3355 g_error ("FIXME: interface method lookup: %s (in method %s)", class->name
, method
->name
);
3356 if (!(class->flags
& TYPE_ATTRIBUTE_INTERFACE
) && class->interface_offsets
!= NULL
)
3357 mono_class_vtable (domain
, class);
3362 case MonoInlineMethod
:
3363 if (method
->wrapper_type
== MONO_WRAPPER_NONE
&& *ip
!= CEE_CALLI
) {
3364 m
= mono_get_method_full (image
, read32 (ip
+ 1), NULL
, generic_context
);
3366 g_free (is_bb_start
);
3367 g_error ("FIXME: where to get method and class string?");
3369 // return mono_get_exception_missing_method ();
3371 mono_class_init (m
->klass
);
3372 if (!mono_class_is_interface (m
->klass
))
3373 mono_class_vtable (domain
, m
->klass
);
3377 case MonoInlineField
:
3381 case MonoShortInlineR
:
3384 case MonoInlineBrTarget
:
3385 offset
= read32 (ip
+ 1);
3387 backwards
= offset
< 0;
3388 offset
+= ip
- header
->code
;
3389 g_assert (offset
>= 0 && offset
< header
->code_size
);
3390 is_bb_start
[offset
] |= backwards
? 2 : 1;
3392 case MonoShortInlineBrTarget
:
3393 offset
= ((gint8
*)ip
) [1];
3395 backwards
= offset
< 0;
3396 offset
+= ip
- header
->code
;
3397 g_assert (offset
>= 0 && offset
< header
->code_size
);
3398 is_bb_start
[offset
] |= backwards
? 2 : 1;
3403 case MonoShortInlineVar
:
3404 case MonoShortInlineI
:
3407 case MonoInlineSwitch
: {
3409 const unsigned char *next_ip
;
3413 next_ip
= ip
+ 4 * n
;
3414 for (i
= 0; i
< n
; i
++) {
3415 offset
= read32 (ip
);
3416 backwards
= offset
< 0;
3417 offset
+= next_ip
- header
->code
;
3418 g_assert (offset
>= 0 && offset
< header
->code_size
);
3419 is_bb_start
[offset
] |= backwards
? 2 : 1;
3429 g_assert_not_reached ();
3432 // g_printerr ("TRANSFORM(0x%016lx): end %s::%s\n", mono_thread_current (), method->klass->name, method->name);
3434 /* the rest needs to be locked so it is only done once */
3435 mono_os_mutex_lock(&calc_section
);
3436 if (runtime_method
->transformed
) {
3437 mono_os_mutex_unlock(&calc_section
);
3438 g_free (is_bb_start
);
3439 mono_profiler_method_end_jit (method
, NULL
, MONO_PROFILE_OK
);
3443 runtime_method
->local_offsets
= g_malloc (header
->num_locals
* sizeof(guint32
));
3444 runtime_method
->stack_size
= (sizeof (stackval
) + 2) * header
->max_stack
; /* + 1 for returns of called functions + 1 for 0-ing in trace*/
3445 runtime_method
->stack_size
= (runtime_method
->stack_size
+ 7) & ~7;
3447 for (i
= 0; i
< header
->num_locals
; ++i
) {
3448 size
= mono_type_size (header
->locals
[i
], &align
);
3449 offset
+= align
- 1;
3450 offset
&= ~(align
- 1);
3451 runtime_method
->local_offsets
[i
] = offset
;
3454 offset
= (offset
+ 7) & ~7;
3455 runtime_method
->locals_size
= offset
;
3456 g_assert (runtime_method
->locals_size
< 65536);
3458 runtime_method
->arg_offsets
= g_malloc ((!!signature
->hasthis
+ signature
->param_count
) * sizeof(guint32
));
3460 if (signature
->hasthis
) {
3461 g_assert (!signature
->pinvoke
);
3462 size
= mono_type_stack_size (&method
->klass
->byval_arg
, &align
);
3463 offset
+= align
- 1;
3464 offset
&= ~(align
- 1);
3465 runtime_method
->arg_offsets
[0] = offset
;
3469 for (i
= 0; i
< signature
->param_count
; ++i
) {
3470 if (signature
->pinvoke
) {
3472 size
= mono_type_native_stack_size (signature
->params
[i
], &dummy
);
3476 size
= mono_type_stack_size (signature
->params
[i
], &align
);
3477 offset
+= align
- 1;
3478 offset
&= ~(align
- 1);
3479 runtime_method
->arg_offsets
[i
+ !!signature
->hasthis
] = offset
;
3482 offset
= (offset
+ 7) & ~7;
3483 runtime_method
->args_size
= offset
;
3484 g_assert (runtime_method
->args_size
< 10000);
3486 generate (method
, runtime_method
, is_bb_start
, generic_context
);
3488 g_free (is_bb_start
);
3490 mono_profiler_method_end_jit (method
, NULL
, MONO_PROFILE_OK
);
3491 runtime_method
->transformed
= TRUE
;
3492 mono_os_mutex_unlock(&calc_section
);