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 ADD_CODE (&td
, MINT_LDFLDA
);
1999 ADD_CODE (&td
, klass
->valuetype
? field
->offset
- sizeof (MonoObject
) : field
->offset
);
2002 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_MP
);
2005 CHECK_STACK (&td
, 1);
2006 token
= read32 (td
.ip
+ 1);
2007 field
= mono_field_from_token (image
, token
, &klass
, generic_context
);
2008 gboolean is_static
= !!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
);
2009 mono_class_init (klass
);
2011 MonoClass
*field_klass
= mono_class_from_mono_type (field
->type
);
2012 mt
= mint_type (&field_klass
->byval_arg
);
2013 if (klass
->marshalbyref
) {
2014 g_assert (!is_static
);
2015 ADD_CODE(&td
, mt
== MINT_TYPE_VT
? MINT_LDRMFLD_VT
: MINT_LDRMFLD
);
2016 ADD_CODE(&td
, get_data_item_index (&td
, field
));
2019 ADD_CODE (&td
, MINT_POP
);
2021 ADD_CODE (&td
, mt
== MINT_TYPE_VT
? MINT_LDSFLD_VT
: MINT_LDSFLD
);
2022 ADD_CODE (&td
, get_data_item_index (&td
, field
));
2024 ADD_CODE (&td
, MINT_LDFLD_I1
+ mt
- MINT_TYPE_I1
);
2025 ADD_CODE (&td
, klass
->valuetype
? field
->offset
- sizeof(MonoObject
) : field
->offset
);
2028 if (mt
== MINT_TYPE_VT
) {
2029 int size
= mono_class_value_size (field_klass
, NULL
);
2031 WRITE32(&td
, &size
);
2033 if (td
.sp
[-1].type
== STACK_TYPE_VT
) {
2034 int size
= mono_class_value_size (klass
, NULL
);
2035 size
= (size
+ 7) & ~7;
2037 ADD_CODE (&td
, MINT_VTRESULT
);
2039 WRITE32 (&td
, &size
);
2042 SET_TYPE(td
.sp
- 1, stack_type
[mt
], field_klass
);
2046 CHECK_STACK (&td
, 2);
2047 token
= read32 (td
.ip
+ 1);
2048 field
= mono_field_from_token (image
, token
, &klass
, generic_context
);
2049 gboolean is_static
= !!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
);
2050 mono_class_init (klass
);
2051 mt
= mint_type(field
->type
);
2053 if (klass
->marshalbyref
) {
2054 g_assert (!is_static
);
2055 ADD_CODE(&td
, mt
== MINT_TYPE_VT
? MINT_STRMFLD_VT
: MINT_STRMFLD
);
2056 ADD_CODE(&td
, get_data_item_index (&td
, field
));
2059 ADD_CODE (&td
, MINT_POP
);
2061 ADD_CODE (&td
, mt
== MINT_TYPE_VT
? MINT_STSFLD_VT
: MINT_STSFLD
);
2062 ADD_CODE (&td
, get_data_item_index (&td
, field
));
2064 ADD_CODE (&td
, MINT_STFLD_I1
+ mt
- MINT_TYPE_I1
);
2065 ADD_CODE (&td
, klass
->valuetype
? field
->offset
- sizeof(MonoObject
) : field
->offset
);
2068 if (mt
== MINT_TYPE_VT
) {
2069 MonoClass
*klass
= mono_class_from_mono_type (field
->type
);
2070 int size
= mono_class_value_size (klass
, NULL
);
2072 WRITE32(&td
, &size
);
2079 token
= read32 (td
.ip
+ 1);
2080 field
= mono_field_from_token (image
, token
, &klass
, generic_context
);
2081 ADD_CODE(&td
, MINT_LDSFLDA
);
2082 ADD_CODE(&td
, get_data_item_index (&td
, field
));
2084 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_MP
);
2087 token
= read32 (td
.ip
+ 1);
2088 field
= mono_field_from_token (image
, token
, &klass
, generic_context
);
2089 mt
= mint_type(field
->type
);
2090 ADD_CODE(&td
, mt
== MINT_TYPE_VT
? MINT_LDSFLD_VT
: MINT_LDSFLD
);
2091 ADD_CODE(&td
, get_data_item_index (&td
, field
));
2093 if (mt
== MINT_TYPE_VT
) {
2094 MonoClass
*klass
= mono_class_from_mono_type (field
->type
);
2095 int size
= mono_class_value_size (klass
, NULL
);
2097 WRITE32(&td
, &size
);
2098 klass
= field
->type
->data
.klass
;
2100 if (mt
== MINT_TYPE_O
)
2101 klass
= mono_class_from_mono_type (field
->type
);
2104 PUSH_TYPE(&td
, stack_type
[mt
], klass
);
2107 CHECK_STACK (&td
, 1);
2108 token
= read32 (td
.ip
+ 1);
2109 field
= mono_field_from_token (image
, token
, &klass
, generic_context
);
2110 mt
= mint_type(field
->type
);
2111 ADD_CODE(&td
, mt
== MINT_TYPE_VT
? MINT_STSFLD_VT
: MINT_STSFLD
);
2112 ADD_CODE(&td
, get_data_item_index (&td
, field
));
2113 if (mt
== MINT_TYPE_VT
) {
2114 MonoClass
*klass
= mono_class_from_mono_type (field
->type
);
2115 int size
= mono_class_value_size (klass
, NULL
);
2117 WRITE32 (&td
, &size
);
2124 token
= read32 (td
.ip
+ 1);
2126 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
2127 klass
= (MonoClass
*)mono_method_get_wrapper_data (method
, token
);
2129 klass
= mono_class_get_full (image
, token
, generic_context
);
2131 ADD_CODE(&td
, td
.sp
[-1].type
== STACK_TYPE_VT
? MINT_STOBJ_VT
: MINT_STOBJ
);
2132 ADD_CODE(&td
, get_data_item_index (&td
, klass
));
2133 if (td
.sp
[-1].type
== STACK_TYPE_VT
) {
2134 size
= mono_class_value_size (klass
, NULL
);
2135 size
= (size
+ 7) & ~7;
2142 case CEE_CONV_OVF_I_UN
:
2143 case CEE_CONV_OVF_U_UN
:
2144 CHECK_STACK (&td
, 1);
2145 switch (td
.sp
[-1].type
) {
2147 #if SIZEOF_VOID_P == 8
2148 ADD_CODE(&td
, MINT_CONV_OVF_I8_UN_R8
);
2150 ADD_CODE(&td
, MINT_CONV_OVF_I4_UN_R8
);
2154 #if SIZEOF_VOID_P == 4
2155 ADD_CODE (&td
, MINT_CONV_OVF_I4_UN_I8
);
2159 #if SIZEOF_VOID_P == 8
2160 ADD_CODE(&td
, MINT_CONV_I8_U4
);
2164 g_assert_not_reached ();
2167 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
2170 case CEE_CONV_OVF_I8_UN
:
2171 case CEE_CONV_OVF_U8_UN
:
2172 CHECK_STACK (&td
, 1);
2173 switch (td
.sp
[-1].type
) {
2175 ADD_CODE(&td
, MINT_CONV_OVF_I8_UN_R8
);
2178 if (*td
.ip
== CEE_CONV_OVF_I8_UN
)
2179 ADD_CODE (&td
, MINT_CONV_OVF_I8_U8
);
2182 ADD_CODE(&td
, MINT_CONV_I8_U4
);
2185 g_assert_not_reached ();
2188 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
2193 CHECK_STACK (&td
, 1);
2194 token
= read32 (td
.ip
+ 1);
2195 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
2196 klass
= (MonoClass
*)mono_method_get_wrapper_data (method
, token
);
2198 klass
= mono_class_get_full (image
, token
, generic_context
);
2200 if (mono_class_is_nullable (klass
)) {
2201 MonoMethod
*target_method
= mono_class_get_method_from_name (klass
, "Box", 1);
2202 /* td.ip is incremented by interp_transform_call */
2203 interp_transform_call (&td
, method
, target_method
, domain
, generic_context
, is_bb_start
, body_start_offset
, NULL
, FALSE
);
2204 } else if (!klass
->valuetype
) {
2205 /* already boxed, do nothing. */
2208 if (mint_type (&klass
->byval_arg
) == MINT_TYPE_VT
&& !klass
->enumtype
) {
2209 size
= mono_class_value_size (klass
, NULL
);
2210 size
= (size
+ 7) & ~7;
2213 ADD_CODE(&td
, MINT_BOX
);
2214 ADD_CODE(&td
, get_data_item_index (&td
, klass
));
2216 SET_TYPE(td
.sp
- 1, STACK_TYPE_O
, klass
);
2223 CHECK_STACK (&td
, 1);
2224 token
= read32 (td
.ip
+ 1);
2226 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
2227 klass
= (MonoClass
*)mono_method_get_wrapper_data (method
, token
);
2229 klass
= mono_class_get_full (image
, token
, generic_context
);
2231 unsigned char lentype
= (td
.sp
- 1)->type
;
2232 if (lentype
== STACK_TYPE_I8
) {
2233 /* mimic mini behaviour */
2234 ADD_CODE (&td
, MINT_CONV_OVF_U4_I8
);
2236 g_assert (lentype
== STACK_TYPE_I4
);
2237 ADD_CODE (&td
, MINT_CONV_OVF_U4_I4
);
2239 SET_SIMPLE_TYPE (td
.sp
- 1, STACK_TYPE_I4
);
2240 ADD_CODE (&td
, MINT_NEWARR
);
2241 ADD_CODE (&td
, get_data_item_index (&td
, klass
));
2242 SET_TYPE (td
.sp
- 1, STACK_TYPE_O
, klass
);
2247 CHECK_STACK (&td
, 1);
2248 SIMPLE_OP (td
, MINT_LDLEN
);
2249 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I
);
2252 CHECK_STACK (&td
, 2);
2254 token
= read32 (td
.ip
+ 1);
2256 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
2257 klass
= (MonoClass
*) mono_method_get_wrapper_data (method
, token
);
2259 klass
= mono_class_get_full (image
, token
, generic_context
);
2261 if (!klass
->valuetype
&& method
->wrapper_type
== MONO_WRAPPER_NONE
&& !readonly
) {
2262 ADD_CODE (&td
, MINT_LDELEMA_TC
);
2264 ADD_CODE (&td
, MINT_LDELEMA
);
2266 ADD_CODE (&td
, get_data_item_index (&td
, klass
));
2267 /* according to spec, ldelema bytecode is only used for 1-dim arrays */
2273 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_MP
);
2276 CHECK_STACK (&td
, 2);
2278 SIMPLE_OP (td
, MINT_LDELEM_I1
);
2280 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2283 CHECK_STACK (&td
, 2);
2285 SIMPLE_OP (td
, MINT_LDELEM_U1
);
2287 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2290 CHECK_STACK (&td
, 2);
2292 SIMPLE_OP (td
, MINT_LDELEM_I2
);
2294 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2297 CHECK_STACK (&td
, 2);
2299 SIMPLE_OP (td
, MINT_LDELEM_U2
);
2301 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2304 CHECK_STACK (&td
, 2);
2306 SIMPLE_OP (td
, MINT_LDELEM_I4
);
2308 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2311 CHECK_STACK (&td
, 2);
2313 SIMPLE_OP (td
, MINT_LDELEM_U4
);
2315 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2318 CHECK_STACK (&td
, 2);
2320 SIMPLE_OP (td
, MINT_LDELEM_I8
);
2322 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
2325 CHECK_STACK (&td
, 2);
2327 SIMPLE_OP (td
, MINT_LDELEM_I
);
2329 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I
);
2332 CHECK_STACK (&td
, 2);
2334 SIMPLE_OP (td
, MINT_LDELEM_R4
);
2336 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
2339 CHECK_STACK (&td
, 2);
2341 SIMPLE_OP (td
, MINT_LDELEM_R8
);
2343 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
2345 case CEE_LDELEM_REF
:
2346 CHECK_STACK (&td
, 2);
2348 SIMPLE_OP (td
, MINT_LDELEM_REF
);
2350 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_O
);
2353 CHECK_STACK (&td
, 2);
2354 token
= read32 (td
.ip
+ 1);
2355 klass
= mono_class_get_full (image
, token
, generic_context
);
2356 switch (mint_type (&klass
->byval_arg
)) {
2359 SIMPLE_OP (td
, MINT_LDELEM_I1
);
2361 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2365 SIMPLE_OP (td
, MINT_LDELEM_U1
);
2367 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2371 SIMPLE_OP (td
, MINT_LDELEM_U2
);
2373 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2377 SIMPLE_OP (td
, MINT_LDELEM_I2
);
2379 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2383 SIMPLE_OP (td
, MINT_LDELEM_I4
);
2385 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2389 SIMPLE_OP (td
, MINT_LDELEM_I8
);
2391 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
2395 SIMPLE_OP (td
, MINT_LDELEM_R4
);
2397 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
2401 SIMPLE_OP (td
, MINT_LDELEM_R8
);
2403 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
2407 SIMPLE_OP (td
, MINT_LDELEM_REF
);
2409 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_O
);
2411 case MINT_TYPE_VT
: {
2412 int size
= mono_class_value_size (klass
, NULL
);
2414 SIMPLE_OP (td
, MINT_LDELEM_VT
);
2415 ADD_CODE (&td
, get_data_item_index (&td
, klass
));
2416 WRITE32 (&td
, &size
);
2418 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_VT
);
2419 PUSH_VT (&td
, size
);
2423 GString
*res
= g_string_new ("");
2424 mono_type_get_desc (res
, &klass
->byval_arg
, TRUE
);
2425 g_print ("LDELEM: %s -> %d (%s)\n", klass
->name
, mint_type (&klass
->byval_arg
), res
->str
);
2426 g_string_free (res
, TRUE
);
2434 CHECK_STACK (&td
, 3);
2436 SIMPLE_OP (td
, MINT_STELEM_I
);
2440 CHECK_STACK (&td
, 3);
2442 SIMPLE_OP (td
, MINT_STELEM_I1
);
2446 CHECK_STACK (&td
, 3);
2448 SIMPLE_OP (td
, MINT_STELEM_I2
);
2452 CHECK_STACK (&td
, 3);
2454 SIMPLE_OP (td
, MINT_STELEM_I4
);
2458 CHECK_STACK (&td
, 3);
2460 SIMPLE_OP (td
, MINT_STELEM_I8
);
2464 CHECK_STACK (&td
, 3);
2466 SIMPLE_OP (td
, MINT_STELEM_R4
);
2470 CHECK_STACK (&td
, 3);
2472 SIMPLE_OP (td
, MINT_STELEM_R8
);
2475 case CEE_STELEM_REF
:
2476 CHECK_STACK (&td
, 3);
2478 SIMPLE_OP (td
, MINT_STELEM_REF
);
2482 CHECK_STACK (&td
, 3);
2484 token
= read32 (td
.ip
+ 1);
2485 klass
= mono_class_get_full (image
, token
, generic_context
);
2486 switch (mint_type (&klass
->byval_arg
)) {
2488 SIMPLE_OP (td
, MINT_STELEM_U1
);
2491 SIMPLE_OP (td
, MINT_STELEM_I4
);
2494 SIMPLE_OP (td
, MINT_STELEM_REF
);
2496 case MINT_TYPE_VT
: {
2497 int size
= mono_class_value_size (klass
, NULL
);
2498 SIMPLE_OP (td
, MINT_STELEM_VT
);
2499 ADD_CODE (&td
, get_data_item_index (&td
, klass
));
2500 WRITE32 (&td
, &size
);
2505 GString
*res
= g_string_new ("");
2506 mono_type_get_desc (res
, &klass
->byval_arg
, TRUE
);
2507 g_print ("STELEM: %s -> %d (%s)\n", klass
->name
, mint_type (&klass
->byval_arg
), res
->str
);
2508 g_string_free (res
, TRUE
);
2517 case CEE_CONV_OVF_U1
:
2519 case CEE_CONV_OVF_I8
:
2521 #if SIZEOF_VOID_P == 8
2522 case CEE_CONV_OVF_U
:
2524 case CEE_REFANYVAL
: ves_abort(); break;
2527 CHECK_STACK (&td
, 1);
2528 SIMPLE_OP (td
, MINT_CKFINITE
);
2530 case CEE_CONV_OVF_I1
:
2531 case CEE_CONV_OVF_I1_UN
:
2532 CHECK_STACK (&td
, 1);
2533 switch (td
.sp
[-1].type
) {
2535 ADD_CODE(&td
, MINT_CONV_OVF_I1_R8
);
2538 ADD_CODE(&td
, MINT_CONV_OVF_I1_I4
);
2541 ADD_CODE(&td
, MINT_CONV_OVF_I1_I8
);
2544 g_assert_not_reached ();
2547 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2549 case CEE_CONV_OVF_U1
:
2550 case CEE_CONV_OVF_U1_UN
:
2551 CHECK_STACK (&td
, 1);
2552 switch (td
.sp
[-1].type
) {
2554 ADD_CODE(&td
, MINT_CONV_OVF_U1_R8
);
2557 ADD_CODE(&td
, MINT_CONV_OVF_U1_I4
);
2560 ADD_CODE(&td
, MINT_CONV_OVF_U1_I8
);
2563 g_assert_not_reached ();
2566 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2568 case CEE_CONV_OVF_I2
:
2569 case CEE_CONV_OVF_I2_UN
:
2570 CHECK_STACK (&td
, 1);
2571 switch (td
.sp
[-1].type
) {
2573 ADD_CODE(&td
, MINT_CONV_OVF_I2_R8
);
2576 ADD_CODE(&td
, MINT_CONV_OVF_I2_I4
);
2579 ADD_CODE(&td
, MINT_CONV_OVF_I2_I8
);
2582 g_assert_not_reached ();
2585 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2587 case CEE_CONV_OVF_U2_UN
:
2588 case CEE_CONV_OVF_U2
:
2589 CHECK_STACK (&td
, 1);
2590 switch (td
.sp
[-1].type
) {
2592 ADD_CODE(&td
, MINT_CONV_OVF_U2_R8
);
2595 ADD_CODE(&td
, MINT_CONV_OVF_U2_I4
);
2598 ADD_CODE(&td
, MINT_CONV_OVF_U2_I8
);
2601 g_assert_not_reached ();
2604 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2606 #if SIZEOF_VOID_P == 4
2607 case CEE_CONV_OVF_I
:
2609 case CEE_CONV_OVF_I4
:
2610 case CEE_CONV_OVF_I4_UN
:
2611 CHECK_STACK (&td
, 1);
2612 switch (td
.sp
[-1].type
) {
2614 ADD_CODE(&td
, MINT_CONV_OVF_I4_R8
);
2617 if (*td
.ip
== CEE_CONV_OVF_I4_UN
)
2618 ADD_CODE(&td
, MINT_CONV_OVF_I4_U4
);
2621 if (*td
.ip
== CEE_CONV_OVF_I4_UN
)
2622 ADD_CODE (&td
, MINT_CONV_OVF_I4_U8
);
2624 ADD_CODE (&td
, MINT_CONV_OVF_I4_I8
);
2627 g_assert_not_reached ();
2630 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2632 #if SIZEOF_VOID_P == 4
2633 case CEE_CONV_OVF_U
:
2635 case CEE_CONV_OVF_U4
:
2636 case CEE_CONV_OVF_U4_UN
:
2637 CHECK_STACK (&td
, 1);
2638 switch (td
.sp
[-1].type
) {
2640 ADD_CODE(&td
, MINT_CONV_OVF_U4_R8
);
2643 if (*td
.ip
!= CEE_CONV_OVF_U4_UN
)
2644 ADD_CODE(&td
, MINT_CONV_OVF_U4_I4
);
2647 ADD_CODE(&td
, MINT_CONV_OVF_U4_I8
);
2650 g_assert_not_reached ();
2653 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2655 #if SIZEOF_VOID_P == 8
2656 case CEE_CONV_OVF_I
:
2658 case CEE_CONV_OVF_I8
:
2659 CHECK_STACK (&td
, 1);
2660 switch (td
.sp
[-1].type
) {
2662 ADD_CODE(&td
, MINT_CONV_OVF_I8_R8
);
2665 ADD_CODE(&td
, MINT_CONV_I8_I4
);
2670 g_assert_not_reached ();
2673 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
2675 #if SIZEOF_VOID_P == 8
2676 case CEE_CONV_OVF_U
:
2678 case CEE_CONV_OVF_U8
:
2679 CHECK_STACK (&td
, 1);
2680 switch (td
.sp
[-1].type
) {
2682 ADD_CODE(&td
, MINT_CONV_OVF_U8_R8
);
2685 ADD_CODE(&td
, MINT_CONV_OVF_U8_I4
);
2688 ADD_CODE (&td
, MINT_CONV_OVF_U8_I8
);
2691 g_assert_not_reached ();
2694 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
2699 token
= read32 (td
.ip
+ 1);
2700 if (method
->wrapper_type
== MONO_WRAPPER_DYNAMIC_METHOD
|| method
->wrapper_type
== MONO_WRAPPER_SYNCHRONIZED
) {
2701 handle
= mono_method_get_wrapper_data (method
, token
);
2702 klass
= (MonoClass
*) mono_method_get_wrapper_data (method
, token
+ 1);
2703 if (klass
== mono_defaults
.typehandle_class
)
2704 handle
= &((MonoClass
*) handle
)->byval_arg
;
2706 handle
= mono_ldtoken (image
, token
, &klass
, generic_context
);
2708 mt
= mint_type (&klass
->byval_arg
);
2709 g_assert (mt
== MINT_TYPE_VT
);
2710 size
= mono_class_value_size (klass
, NULL
);
2711 g_assert (size
== sizeof(gpointer
));
2712 PUSH_VT (&td
, sizeof(gpointer
));
2713 ADD_CODE (&td
, MINT_LDTOKEN
);
2714 ADD_CODE (&td
, get_data_item_index (&td
, handle
));
2716 SET_TYPE (td
.sp
, stack_type
[mt
], klass
);
2722 binary_arith_op(&td
, MINT_ADD_OVF_I4
);
2725 case CEE_ADD_OVF_UN
:
2726 binary_arith_op(&td
, MINT_ADD_OVF_UN_I4
);
2730 binary_arith_op(&td
, MINT_MUL_OVF_I4
);
2733 case CEE_MUL_OVF_UN
:
2734 binary_arith_op(&td
, MINT_MUL_OVF_UN_I4
);
2738 binary_arith_op(&td
, MINT_SUB_OVF_I4
);
2741 case CEE_SUB_OVF_UN
:
2742 binary_arith_op(&td
, MINT_SUB_OVF_UN_I4
);
2745 case CEE_ENDFINALLY
:
2746 SIMPLE_OP (td
, MINT_ENDFINALLY
);
2747 generating_code
= 0;
2751 handle_branch (&td
, MINT_LEAVE_S
, MINT_LEAVE
, 5 + read32 (td
.ip
+ 1));
2753 generating_code
= 0;
2757 handle_branch (&td
, MINT_LEAVE_S
, MINT_LEAVE
, 2 + (gint8
)td
.ip
[1]);
2759 generating_code
= 0;
2764 case CEE_MONO_CALLI_EXTRA_ARG
:
2765 /* Same as CEE_CALLI, except that we drop the extra arg required for llvm specific behaviour */
2766 ADD_CODE (&td
, MINT_POP
);
2769 interp_transform_call (&td
, method
, NULL
, domain
, generic_context
, is_bb_start
, body_start_offset
, NULL
, FALSE
);
2771 case CEE_MONO_JIT_ICALL_ADDR
: {
2774 MonoJitICallInfo
*info
;
2776 token
= read32 (td
.ip
+ 1);
2778 func
= mono_method_get_wrapper_data (method
, token
);
2779 info
= mono_find_jit_icall_by_addr (func
);
2781 ADD_CODE (&td
, MINT_LDFTN
);
2782 ADD_CODE (&td
, get_data_item_index (&td
, func
));
2783 PUSH_SIMPLE_TYPE (&td
, STACK_TYPE_I
);
2786 case CEE_MONO_ICALL
: {
2789 MonoJitICallInfo
*info
;
2791 token
= read32 (td
.ip
+ 1);
2793 func
= mono_method_get_wrapper_data (method
, token
);
2794 info
= mono_find_jit_icall_by_addr (func
);
2797 CHECK_STACK (&td
, info
->sig
->param_count
);
2798 switch (info
->sig
->param_count
) {
2800 if (MONO_TYPE_IS_VOID (info
->sig
->ret
))
2801 ADD_CODE (&td
,MINT_ICALL_V_V
);
2803 ADD_CODE (&td
, MINT_ICALL_V_P
);
2806 if (MONO_TYPE_IS_VOID (info
->sig
->ret
))
2807 ADD_CODE (&td
,MINT_ICALL_P_V
);
2809 ADD_CODE (&td
,MINT_ICALL_P_P
);
2812 if (MONO_TYPE_IS_VOID (info
->sig
->ret
)) {
2813 if (info
->sig
->params
[1]->type
== MONO_TYPE_I4
)
2814 ADD_CODE (&td
,MINT_ICALL_PI_V
);
2816 ADD_CODE (&td
,MINT_ICALL_PP_V
);
2818 if (info
->sig
->params
[1]->type
== MONO_TYPE_I4
)
2819 ADD_CODE (&td
,MINT_ICALL_PI_P
);
2821 ADD_CODE (&td
,MINT_ICALL_PP_P
);
2825 g_assert (MONO_TYPE_IS_VOID (info
->sig
->ret
));
2826 if (info
->sig
->params
[2]->type
== MONO_TYPE_I4
)
2827 ADD_CODE (&td
,MINT_ICALL_PPI_V
);
2829 ADD_CODE (&td
,MINT_ICALL_PPP_V
);
2832 g_assert_not_reached ();
2835 if (func
== mono_ftnptr_to_delegate
) {
2836 g_error ("TODO: ?");
2838 ADD_CODE(&td
, get_data_item_index (&td
, func
));
2839 td
.sp
-= info
->sig
->param_count
;
2841 if (!MONO_TYPE_IS_VOID (info
->sig
->ret
)) {
2843 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I
);
2847 case CEE_MONO_VTADDR
: {
2849 CHECK_STACK (&td
, 1);
2850 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
)
2851 size
= mono_class_native_size(td
.sp
[-1].klass
, NULL
);
2853 size
= mono_class_value_size(td
.sp
[-1].klass
, NULL
);
2854 size
= (size
+ 7) & ~7;
2855 ADD_CODE(&td
, MINT_VTRESULT
);
2857 WRITE32(&td
, &size
);
2860 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_MP
);
2863 case CEE_MONO_LDPTR
:
2864 case CEE_MONO_CLASSCONST
:
2865 token
= read32 (td
.ip
+ 1);
2867 ADD_CODE(&td
, MINT_MONO_LDPTR
);
2868 ADD_CODE(&td
, get_data_item_index (&td
, mono_method_get_wrapper_data (method
, token
)));
2869 td
.sp
[0].type
= STACK_TYPE_I
;
2872 case CEE_MONO_OBJADDR
:
2873 CHECK_STACK (&td
, 1);
2875 td
.sp
[-1].type
= STACK_TYPE_MP
;
2878 case CEE_MONO_NEWOBJ
:
2879 token
= read32 (td
.ip
+ 1);
2881 ADD_CODE(&td
, MINT_MONO_NEWOBJ
);
2882 ADD_CODE(&td
, get_data_item_index (&td
, mono_method_get_wrapper_data (method
, token
)));
2883 td
.sp
[0].type
= STACK_TYPE_O
;
2886 case CEE_MONO_RETOBJ
:
2887 CHECK_STACK (&td
, 1);
2888 token
= read32 (td
.ip
+ 1);
2890 ADD_CODE(&td
, MINT_MONO_RETOBJ
);
2893 klass
= (MonoClass
*)mono_method_get_wrapper_data (method
, token
);
2895 /*stackval_from_data (signature->ret, frame->retval, sp->data.vt, signature->pinvoke);*/
2897 if (td
.sp
> td
.stack
)
2898 g_warning ("CEE_MONO_RETOBJ: more values on stack: %d", td
.sp
-td
.stack
);
2900 case CEE_MONO_LDNATIVEOBJ
:
2901 token
= read32 (td
.ip
+ 1);
2903 klass
= (MonoClass
*)mono_method_get_wrapper_data (method
, token
);
2904 g_assert(klass
->valuetype
);
2905 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_MP
);
2907 case CEE_MONO_SAVE_LMF
:
2908 case CEE_MONO_RESTORE_LMF
:
2909 case CEE_MONO_NOT_TAKEN
:
2912 case CEE_MONO_LDPTR_INT_REQ_FLAG
:
2913 ADD_CODE (&td
, MINT_MONO_LDPTR
);
2914 ADD_CODE (&td
, get_data_item_index (&td
, mono_thread_interruption_request_flag ()));
2915 PUSH_TYPE (&td
, STACK_TYPE_MP
, NULL
);
2919 g_error ("transform.c: Unimplemented opcode: 0xF0 %02x at 0x%x\n", *td
.ip
, td
.ip
-header
->code
);
2929 case CEE_PREFIXREF
: ves_abort(); break;
2932 * Note: Exceptions thrown when executing a prefixed opcode need
2933 * to take into account the number of prefix bytes (usually the
2934 * throw point is just (ip - n_prefix_bytes).
2940 case CEE_ARGLIST
: ves_abort(); break;
2943 CHECK_STACK(&td
, 2);
2944 if (td
.sp
[-1].type
== STACK_TYPE_O
|| td
.sp
[-1].type
== STACK_TYPE_MP
)
2945 ADD_CODE(&td
, MINT_CEQ_I4
+ STACK_TYPE_I
- STACK_TYPE_I4
);
2947 ADD_CODE(&td
, MINT_CEQ_I4
+ td
.sp
[-1].type
- STACK_TYPE_I4
);
2949 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2953 CHECK_STACK(&td
, 2);
2954 if (td
.sp
[-1].type
== STACK_TYPE_O
|| td
.sp
[-1].type
== STACK_TYPE_MP
)
2955 ADD_CODE(&td
, MINT_CGT_I4
+ STACK_TYPE_I
- STACK_TYPE_I4
);
2957 ADD_CODE(&td
, MINT_CGT_I4
+ td
.sp
[-1].type
- STACK_TYPE_I4
);
2959 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2963 CHECK_STACK(&td
, 2);
2964 if (td
.sp
[-1].type
== STACK_TYPE_O
|| td
.sp
[-1].type
== STACK_TYPE_MP
)
2965 ADD_CODE(&td
, MINT_CGT_UN_I4
+ STACK_TYPE_I
- STACK_TYPE_I4
);
2967 ADD_CODE(&td
, MINT_CGT_UN_I4
+ td
.sp
[-1].type
- STACK_TYPE_I4
);
2969 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2973 CHECK_STACK(&td
, 2);
2974 if (td
.sp
[-1].type
== STACK_TYPE_O
|| td
.sp
[-1].type
== STACK_TYPE_MP
)
2975 ADD_CODE(&td
, MINT_CLT_I4
+ STACK_TYPE_I
- STACK_TYPE_I4
);
2977 ADD_CODE(&td
, MINT_CLT_I4
+ td
.sp
[-1].type
- STACK_TYPE_I4
);
2979 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2983 CHECK_STACK(&td
, 2);
2984 if (td
.sp
[-1].type
== STACK_TYPE_O
|| td
.sp
[-1].type
== STACK_TYPE_MP
)
2985 ADD_CODE(&td
, MINT_CLT_UN_I4
+ STACK_TYPE_I
- STACK_TYPE_I4
);
2987 ADD_CODE(&td
, MINT_CLT_UN_I4
+ td
.sp
[-1].type
- STACK_TYPE_I4
);
2989 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2992 case CEE_LDVIRTFTN
: /* fallthrough */
2995 if (*td
.ip
== CEE_LDVIRTFTN
) {
2996 CHECK_STACK (&td
, 1);
2999 token
= read32 (td
.ip
+ 1);
3000 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
3001 m
= (MonoMethod
*)mono_method_get_wrapper_data (method
, token
);
3003 m
= mono_get_method_full (image
, token
, NULL
, generic_context
);
3005 if (method
->wrapper_type
== MONO_WRAPPER_NONE
&& m
->iflags
& METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED
)
3006 m
= mono_marshal_get_synchronized_wrapper (m
);
3008 ADD_CODE(&td
, *td
.ip
== CEE_LDFTN
? MINT_LDFTN
: MINT_LDVIRTFTN
);
3009 ADD_CODE(&td
, get_data_item_index (&td
, mono_interp_get_runtime_method (domain
, m
, &error
)));
3010 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
3012 PUSH_SIMPLE_TYPE (&td
, STACK_TYPE_F
);
3016 load_arg (&td
, read16 (td
.ip
+ 1));
3020 int n
= read16 (td
.ip
+ 1);
3021 if (n
== 0 && signature
->hasthis
) {
3022 g_error ("LDTHISA: NOPE");
3023 ADD_CODE(&td
, MINT_LDTHISA
);
3026 ADD_CODE(&td
, MINT_LDARGA
);
3027 ADD_CODE(&td
, td
.rtm
->arg_offsets
[n
]); /* FIX for large offsets */
3029 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_MP
);
3034 store_arg (&td
, read16 (td
.ip
+ 1));
3038 load_local (&td
, read16 (td
.ip
+ 1));
3042 ADD_CODE(&td
, MINT_LDLOCA_S
);
3043 ADD_CODE(&td
, td
.rtm
->local_offsets
[read16 (td
.ip
+ 1)]);
3044 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_MP
);
3048 store_local (&td
, read16 (td
.ip
+ 1));
3052 CHECK_STACK (&td
, 1);
3053 #if SIZEOF_VOID_P == 8
3054 if (td
.sp
[-1].type
== STACK_TYPE_I8
)
3055 ADD_CODE(&td
, MINT_CONV_I4_I8
);
3057 ADD_CODE(&td
, MINT_LOCALLOC
);
3058 if (td
.sp
!= td
.stack
+ 1)
3059 g_warning("CEE_LOCALLOC: stack not empty");
3061 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_MP
);
3064 case CEE_UNUSED57
: ves_abort(); break;
3065 case CEE_ENDFILTER
: ves_abort(); break;
3067 case CEE_UNALIGNED_
:
3069 /* FIX: should do something? */;
3073 /* FIX: should do something? */;
3077 /* FIX: should do something? */;
3080 CHECK_STACK(&td
, 1);
3081 token
= read32 (td
.ip
+ 1);
3082 klass
= mono_class_get_full (image
, token
, generic_context
);
3083 if (klass
->valuetype
) {
3084 ADD_CODE (&td
, MINT_INITOBJ
);
3085 i32
= mono_class_value_size (klass
, NULL
);
3086 WRITE32 (&td
, &i32
);
3088 ADD_CODE (&td
, MINT_LDNULL
);
3089 ADD_CODE (&td
, MINT_STIND_REF
);
3095 CHECK_STACK(&td
, 3);
3096 /* FIX? convert length to I8? */
3097 ADD_CODE(&td
, MINT_CPBLK
);
3105 case CEE_CONSTRAINED_
:
3106 token
= read32 (td
.ip
+ 1);
3107 constrained_class
= mono_class_get_full (image
, token
, generic_context
);
3108 mono_class_init (constrained_class
);
3112 CHECK_STACK(&td
, 3);
3113 ADD_CODE(&td
, MINT_INITBLK
);
3118 /* FIXME: implement */
3123 SIMPLE_OP (td
, MINT_RETHROW
);
3124 generating_code
= 0;
3128 token
= read32 (td
.ip
+ 1);
3130 if (mono_metadata_token_table (token
) == MONO_TABLE_TYPESPEC
&& !image_is_dynamic (method
->klass
->image
) && !generic_context
) {
3132 MonoType
*type
= mono_type_create_from_typespec (image
, token
);
3133 size
= mono_type_size (type
, &align
);
3136 MonoClass
*szclass
= mono_class_get_full (image
, token
, generic_context
);
3137 mono_class_init (szclass
);
3139 if (!szclass
->valuetype
)
3140 THROW_EX (mono_exception_from_name (mono_defaults
.corlib
, "System", "InvalidProgramException"), ip
- 5);
3142 size
= mono_type_size (&szclass
->byval_arg
, &align
);
3144 ADD_CODE(&td
, MINT_LDC_I4
);
3145 WRITE32(&td
, &size
);
3146 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I4
);
3150 case CEE_REFANYTYPE
: ves_abort(); break;
3153 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
);
3157 g_error ("transform.c: Unimplemented opcode: %02x at 0x%x\n", *td
.ip
, td
.ip
-header
->code
);
3160 if (td
.new_ip
- td
.new_code
!= new_in_start_offset
)
3161 td
.last_new_ip
= td
.new_code
+ new_in_start_offset
;
3162 else if (td
.is_bb_start
[td
.in_start
- td
.il_code
])
3163 td
.is_bb_start
[td
.ip
- td
.il_code
] = 1;
3165 td
.last_ip
= td
.in_start
;
3168 if (mono_interp_traceopt
) {
3169 const guint16
*p
= td
.new_code
;
3170 printf("Runtime method: %p, VT stack size: %d\n", rtm
, td
.max_vt_sp
);
3171 printf("Calculated stack size: %d, stated size: %d\n", td
.max_stack_height
, header
->max_stack
);
3172 while (p
< td
.new_ip
) {
3173 p
= mono_interp_dis_mintop(td
.new_code
, p
);
3177 g_assert (td
.max_stack_height
<= (header
->max_stack
+ 1));
3179 rtm
->clauses
= mono_mempool_alloc (domain
->mp
, header
->num_clauses
* sizeof(MonoExceptionClause
));
3180 memcpy (rtm
->clauses
, header
->clauses
, header
->num_clauses
* sizeof(MonoExceptionClause
));
3181 rtm
->code
= mono_mempool_alloc (domain
->mp
, (td
.new_ip
- td
.new_code
) * sizeof(gushort
));
3182 memcpy (rtm
->code
, td
.new_code
, (td
.new_ip
- td
.new_code
) * sizeof(gushort
));
3183 g_free (td
.new_code
);
3184 rtm
->new_body_start
= rtm
->code
+ body_start_offset
;
3185 rtm
->num_clauses
= header
->num_clauses
;
3186 for (i
= 0; i
< header
->num_clauses
; i
++) {
3187 MonoExceptionClause
*c
= rtm
->clauses
+ i
;
3188 int end_off
= c
->try_offset
+ c
->try_len
;
3189 c
->try_offset
= td
.in_offsets
[c
->try_offset
];
3190 c
->try_len
= td
.in_offsets
[end_off
] - c
->try_offset
;
3191 end_off
= c
->handler_offset
+ c
->handler_len
;
3192 c
->handler_offset
= td
.in_offsets
[c
->handler_offset
];
3193 c
->handler_len
= td
.in_offsets
[end_off
] - c
->handler_offset
;
3195 rtm
->vt_stack_size
= td
.max_vt_sp
;
3196 rtm
->alloca_size
= rtm
->locals_size
+ rtm
->args_size
+ rtm
->vt_stack_size
+ rtm
->stack_size
;
3197 rtm
->data_items
= mono_mempool_alloc (domain
->mp
, td
.n_data_items
* sizeof (td
.data_items
[0]));
3198 memcpy (rtm
->data_items
, td
.data_items
, td
.n_data_items
* sizeof (td
.data_items
[0]));
3199 g_free (td
.in_offsets
);
3200 g_free (td
.forward_refs
);
3201 for (i
= 0; i
< header
->code_size
; ++i
)
3202 g_free (td
.stack_state
[i
]);
3203 g_free (td
.stack_state
);
3204 g_free (td
.stack_height
);
3205 g_free (td
.vt_stack_size
);
3206 g_free (td
.data_items
);
3208 g_hash_table_destroy (td
.data_hash
);
3211 static mono_mutex_t calc_section
;
3214 mono_interp_transform_init (void)
3216 mono_os_mutex_init_recursive(&calc_section
);
3220 mono_interp_transform_method (RuntimeMethod
*runtime_method
, ThreadContext
*context
)
3222 int i
, align
, size
, offset
;
3223 MonoMethod
*method
= runtime_method
->method
;
3224 MonoImage
*image
= method
->klass
->image
;
3225 MonoMethodHeader
*header
= mono_method_get_header (method
);
3226 MonoMethodSignature
*signature
= mono_method_signature (method
);
3227 register const unsigned char *ip
, *end
;
3228 const MonoOpcode
*opcode
;
3231 MonoDomain
*domain
= mono_domain_get ();
3232 unsigned char *is_bb_start
;
3234 MonoVTable
*method_class_vt
;
3236 MonoGenericContext
*generic_context
= NULL
;
3238 // g_printerr ("TRANSFORM(0x%016lx): begin %s::%s\n", mono_thread_current (), method->klass->name, method->name);
3239 method_class_vt
= mono_class_vtable (domain
, runtime_method
->method
->klass
);
3240 if (!method_class_vt
->initialized
) {
3242 MonoInvocation
*last_env_frame
= context
->env_frame
;
3243 jmp_buf *old_env
= context
->current_env
;
3246 MonoException
*failed
= context
->env_frame
->ex
;
3247 context
->env_frame
->ex
= NULL
;
3248 context
->env_frame
= last_env_frame
;
3249 context
->current_env
= old_env
;
3252 context
->env_frame
= context
->current_frame
;
3253 context
->current_env
= &env
;
3254 mono_runtime_class_init (method_class_vt
);
3255 context
->env_frame
= last_env_frame
;
3256 context
->current_env
= old_env
;
3259 mono_profiler_method_jit (method
); /* sort of... */
3261 if (mono_method_signature (method
)->is_inflated
)
3262 generic_context
= mono_method_get_context (method
);
3264 MonoGenericContainer
*generic_container
= mono_method_get_generic_container (method
);
3265 if (generic_container
)
3266 generic_context
= &generic_container
->context
;
3269 if (method
->iflags
& (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
| METHOD_IMPL_ATTRIBUTE_RUNTIME
)) {
3270 MonoMethod
*nm
= NULL
;
3271 mono_os_mutex_lock(&calc_section
);
3272 if (runtime_method
->transformed
) {
3273 mono_os_mutex_unlock(&calc_section
);
3274 g_error ("FIXME: no jit info?");
3275 mono_profiler_method_end_jit (method
, NULL
, MONO_PROFILE_OK
);
3279 /* assumes all internal calls with an array this are built in... */
3280 if (method
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
&& (! mono_method_signature (method
)->hasthis
|| method
->klass
->rank
== 0)) {
3281 nm
= mono_marshal_get_native_wrapper (method
, TRUE
, FALSE
);
3282 signature
= mono_method_signature (nm
);
3284 const char *name
= method
->name
;
3285 if (method
->klass
->parent
== mono_defaults
.multicastdelegate_class
) {
3286 if (*name
== '.' && (strcmp (name
, ".ctor") == 0)) {
3287 MonoJitICallInfo
*mi
= mono_find_jit_icall_by_name ("ves_icall_mono_delegate_ctor");
3289 char *wrapper_name
= g_strdup_printf ("__icall_wrapper_%s", mi
->name
);
3290 nm
= mono_marshal_get_icall_wrapper (mi
->sig
, wrapper_name
, mi
->func
, TRUE
);
3291 } else if (*name
== 'I' && (strcmp (name
, "Invoke") == 0)) {
3292 nm
= mono_marshal_get_delegate_invoke (method
, NULL
);
3293 } else if (*name
== 'B' && (strcmp (name
, "BeginInvoke") == 0)) {
3294 nm
= mono_marshal_get_delegate_begin_invoke (method
);
3295 } else if (*name
== 'E' && (strcmp (name
, "EndInvoke") == 0)) {
3296 nm
= mono_marshal_get_delegate_end_invoke (method
);
3300 runtime_method
->code
= g_malloc(sizeof(short));
3301 runtime_method
->code
[0] = MINT_CALLRUN
;
3305 runtime_method
->stack_size
= sizeof (stackval
); /* for tracing */
3306 runtime_method
->alloca_size
= runtime_method
->stack_size
;
3307 runtime_method
->transformed
= TRUE
;
3308 mono_os_mutex_unlock(&calc_section
);
3309 mono_profiler_method_end_jit (method
, NULL
, MONO_PROFILE_OK
);
3313 header
= mono_method_get_header (nm
);
3314 mono_os_mutex_unlock(&calc_section
);
3316 g_assert ((signature
->param_count
+ signature
->hasthis
) < 1000);
3317 g_assert (header
->max_stack
< 10000);
3318 /* intern the strings in the method. */
3320 end
= ip
+ header
->code_size
;
3322 is_bb_start
= g_malloc0(header
->code_size
);
3323 is_bb_start
[0] = 1;
3330 else if (in
== 0xf0) {
3332 in
= *ip
+ MONO_CEE_MONO_ICALL
;
3334 opcode
= &mono_opcodes
[in
];
3335 switch (opcode
->argument
) {
3336 case MonoInlineNone
:
3339 case MonoInlineString
:
3340 if (method
->wrapper_type
== MONO_WRAPPER_NONE
)
3341 mono_ldstr (domain
, image
, mono_metadata_token_index (read32 (ip
+ 1)));
3344 case MonoInlineType
:
3345 if (method
->wrapper_type
== MONO_WRAPPER_NONE
) {
3346 class = mono_class_get_full (image
, read32 (ip
+ 1), generic_context
);
3347 mono_class_init (class);
3348 /* quick fix to not do this for the fake ptr classes - probably should not be getting the vtable at all here */
3350 g_error ("FIXME: interface method lookup: %s (in method %s)", class->name
, method
->name
);
3351 if (!(class->flags
& TYPE_ATTRIBUTE_INTERFACE
) && class->interface_offsets
!= NULL
)
3352 mono_class_vtable (domain
, class);
3357 case MonoInlineMethod
:
3358 if (method
->wrapper_type
== MONO_WRAPPER_NONE
&& *ip
!= CEE_CALLI
) {
3359 m
= mono_get_method_full (image
, read32 (ip
+ 1), NULL
, generic_context
);
3361 g_free (is_bb_start
);
3362 g_error ("FIXME: where to get method and class string?");
3364 // return mono_get_exception_missing_method ();
3366 mono_class_init (m
->klass
);
3367 if (!mono_class_is_interface (m
->klass
))
3368 mono_class_vtable (domain
, m
->klass
);
3372 case MonoInlineField
:
3376 case MonoShortInlineR
:
3379 case MonoInlineBrTarget
:
3380 offset
= read32 (ip
+ 1);
3382 backwards
= offset
< 0;
3383 offset
+= ip
- header
->code
;
3384 g_assert (offset
>= 0 && offset
< header
->code_size
);
3385 is_bb_start
[offset
] |= backwards
? 2 : 1;
3387 case MonoShortInlineBrTarget
:
3388 offset
= ((gint8
*)ip
) [1];
3390 backwards
= offset
< 0;
3391 offset
+= ip
- header
->code
;
3392 g_assert (offset
>= 0 && offset
< header
->code_size
);
3393 is_bb_start
[offset
] |= backwards
? 2 : 1;
3398 case MonoShortInlineVar
:
3399 case MonoShortInlineI
:
3402 case MonoInlineSwitch
: {
3404 const unsigned char *next_ip
;
3408 next_ip
= ip
+ 4 * n
;
3409 for (i
= 0; i
< n
; i
++) {
3410 offset
= read32 (ip
);
3411 backwards
= offset
< 0;
3412 offset
+= next_ip
- header
->code
;
3413 g_assert (offset
>= 0 && offset
< header
->code_size
);
3414 is_bb_start
[offset
] |= backwards
? 2 : 1;
3424 g_assert_not_reached ();
3427 // g_printerr ("TRANSFORM(0x%016lx): end %s::%s\n", mono_thread_current (), method->klass->name, method->name);
3429 /* the rest needs to be locked so it is only done once */
3430 mono_os_mutex_lock(&calc_section
);
3431 if (runtime_method
->transformed
) {
3432 mono_os_mutex_unlock(&calc_section
);
3433 g_free (is_bb_start
);
3434 mono_profiler_method_end_jit (method
, NULL
, MONO_PROFILE_OK
);
3438 runtime_method
->local_offsets
= g_malloc (header
->num_locals
* sizeof(guint32
));
3439 runtime_method
->stack_size
= (sizeof (stackval
) + 2) * header
->max_stack
; /* + 1 for returns of called functions + 1 for 0-ing in trace*/
3440 runtime_method
->stack_size
= (runtime_method
->stack_size
+ 7) & ~7;
3442 for (i
= 0; i
< header
->num_locals
; ++i
) {
3443 size
= mono_type_size (header
->locals
[i
], &align
);
3444 offset
+= align
- 1;
3445 offset
&= ~(align
- 1);
3446 runtime_method
->local_offsets
[i
] = offset
;
3449 offset
= (offset
+ 7) & ~7;
3450 runtime_method
->locals_size
= offset
;
3451 g_assert (runtime_method
->locals_size
< 65536);
3453 runtime_method
->arg_offsets
= g_malloc ((!!signature
->hasthis
+ signature
->param_count
) * sizeof(guint32
));
3455 if (signature
->hasthis
) {
3456 g_assert (!signature
->pinvoke
);
3457 size
= mono_type_stack_size (&method
->klass
->byval_arg
, &align
);
3458 offset
+= align
- 1;
3459 offset
&= ~(align
- 1);
3460 runtime_method
->arg_offsets
[0] = offset
;
3464 for (i
= 0; i
< signature
->param_count
; ++i
) {
3465 if (signature
->pinvoke
) {
3467 size
= mono_type_native_stack_size (signature
->params
[i
], &dummy
);
3471 size
= mono_type_stack_size (signature
->params
[i
], &align
);
3472 offset
+= align
- 1;
3473 offset
&= ~(align
- 1);
3474 runtime_method
->arg_offsets
[i
+ !!signature
->hasthis
] = offset
;
3477 offset
= (offset
+ 7) & ~7;
3478 runtime_method
->args_size
= offset
;
3479 g_assert (runtime_method
->args_size
< 10000);
3481 generate (method
, runtime_method
, is_bb_start
, generic_context
);
3483 g_free (is_bb_start
);
3485 mono_profiler_method_end_jit (method
, NULL
, MONO_PROFILE_OK
);
3486 runtime_method
->transformed
= TRUE
;
3487 mono_os_mutex_unlock(&calc_section
);