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 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
22 #include "mono/cil/opcode.def"
42 MonoMethodHeader
*header
;
44 const unsigned char *il_code
;
45 const unsigned char *ip
;
46 const unsigned char *last_ip
;
47 const unsigned char *in_start
;
51 StackInfo
**stack_state
;
54 unsigned char *is_bb_start
;
55 unsigned short *new_code
;
56 unsigned short *new_code_end
;
57 unsigned short *new_ip
;
58 unsigned short *last_new_ip
;
59 unsigned int max_code_size
;
62 unsigned int max_stack_height
;
64 unsigned int max_vt_sp
;
68 GHashTable
*data_hash
;
71 #define MINT_TYPE_I1 0
72 #define MINT_TYPE_U1 1
73 #define MINT_TYPE_I2 2
74 #define MINT_TYPE_U2 3
75 #define MINT_TYPE_I4 4
76 #define MINT_TYPE_I8 5
77 #define MINT_TYPE_R4 6
78 #define MINT_TYPE_R8 7
81 #define MINT_TYPE_VT 10
83 #define STACK_TYPE_I4 0
84 #define STACK_TYPE_I8 1
85 #define STACK_TYPE_R8 2
86 #define STACK_TYPE_O 3
87 #define STACK_TYPE_VT 4
88 #define STACK_TYPE_MP 5
89 #define STACK_TYPE_F 6
91 static const char *stack_type_string
[] = { "I4", "I8", "R8", "O ", "VT", "MP", "F " };
93 #if SIZEOF_VOID_P == 8
94 #define STACK_TYPE_I STACK_TYPE_I8
96 #define STACK_TYPE_I STACK_TYPE_I4
99 static int stack_type
[] = {
100 STACK_TYPE_I4
, /*I1*/
101 STACK_TYPE_I4
, /*U1*/
102 STACK_TYPE_I4
, /*I2*/
103 STACK_TYPE_I4
, /*U2*/
104 STACK_TYPE_I4
, /*I4*/
105 STACK_TYPE_I8
, /*I8*/
106 STACK_TYPE_R8
, /*R4*/
107 STACK_TYPE_R8
, /*R8*/
114 grow_code (TransformData
*td
)
116 unsigned int old_ip_offset
= td
->new_ip
- td
->new_code
;
117 unsigned int old_last_ip_offset
= td
->last_new_ip
- td
->new_code
;
118 g_assert (old_ip_offset
<= td
->max_code_size
);
119 td
->new_code
= g_realloc (td
->new_code
, (td
->max_code_size
*= 2) * sizeof (td
->new_code
[0]));
120 td
->new_code_end
= td
->new_code
+ td
->max_code_size
;
121 td
->new_ip
= td
->new_code
+ old_ip_offset
;
122 td
->last_new_ip
= td
->new_code
+ old_last_ip_offset
;
125 #define ENSURE_CODE(td, n) \
127 if ((td)->new_ip + (n) > (td)->new_code_end) \
131 #define ADD_CODE(td, n) \
133 if ((td)->new_ip == (td)->new_code_end) \
135 *(td)->new_ip++ = (n); \
138 #define CHECK_STACK(td, n) \
140 int stack_size = (td)->sp - (td)->stack; \
141 if (stack_size < (n)) \
142 g_warning ("%s.%s: not enough values (%d < %d) on stack at %04x", \
143 (td)->method->klass->name, (td)->method->name, \
144 stack_size, n, (td)->ip - (td)->il_code); \
147 #define ENSURE_I4(td, sp_off) \
149 if ((td)->sp [-sp_off].type == STACK_TYPE_I8) \
150 ADD_CODE(td, sp_off == 1 ? MINT_CONV_I4_I8 : MINT_CONV_I4_I8_SP); \
154 handle_branch(TransformData
*td
, int short_op
, int long_op
, int offset
)
156 int shorten_branch
= 0;
157 int target
= td
->ip
+ offset
- td
->il_code
;
158 if (target
< 0 || target
>= td
->code_size
)
159 g_assert_not_reached ();
160 if (offset
> 0 && td
->stack_height
[target
] < 0) {
161 td
->stack_height
[target
] = td
->sp
- td
->stack
;
162 if (td
->stack_height
[target
] > 0)
163 td
->stack_state
[target
] = g_memdup (td
->stack
, td
->stack_height
[target
] * sizeof (td
->stack
[0]));
164 td
->vt_stack_size
[target
] = td
->vt_sp
;
167 offset
= td
->in_offsets
[target
] - (td
->new_ip
- td
->new_code
);
168 if (offset
>= -32768) {
172 int prev
= td
->forward_refs
[target
];
173 td
->forward_refs
[td
->ip
- td
->il_code
] = prev
;
174 td
->forward_refs
[target
] = td
->ip
- td
->il_code
;
176 if (td
->header
->code_size
<= 25000) /* FIX to be precise somehow? */
179 if (shorten_branch
) {
180 ADD_CODE(td
, short_op
);
181 ADD_CODE(td
, offset
);
183 ADD_CODE(td
, long_op
);
184 ADD_CODE(td
, * (unsigned short *)(&offset
));
185 ADD_CODE(td
, * ((unsigned short *)&offset
+ 1));
190 one_arg_branch(TransformData
*td
, int mint_op
, int offset
)
192 int type
= td
->sp
[-1].type
== STACK_TYPE_O
|| td
->sp
[-1].type
== STACK_TYPE_MP
? STACK_TYPE_I
: td
->sp
[-1].type
;
193 int long_op
= mint_op
+ type
- STACK_TYPE_I4
;
194 int short_op
= long_op
+ MINT_BRFALSE_I4_S
- MINT_BRFALSE_I4
;
197 handle_branch (td
, short_op
, long_op
, offset
);
201 two_arg_branch(TransformData
*td
, int mint_op
, int offset
)
203 int type1
= td
->sp
[-1].type
== STACK_TYPE_O
|| td
->sp
[-1].type
== STACK_TYPE_MP
? STACK_TYPE_I
: td
->sp
[-1].type
;
204 int type2
= td
->sp
[-2].type
== STACK_TYPE_O
|| td
->sp
[-2].type
== STACK_TYPE_MP
? STACK_TYPE_I
: td
->sp
[-2].type
;
205 int long_op
= mint_op
+ type1
- STACK_TYPE_I4
;
206 int short_op
= long_op
+ MINT_BEQ_I4_S
- MINT_BEQ_I4
;
208 if (type1
== STACK_TYPE_I4
&& type2
== STACK_TYPE_I8
) {
209 ADD_CODE(td
, MINT_CONV_I8_I4
);
210 td
->in_offsets
[td
->ip
- td
->il_code
]++;
211 } else if (type1
== STACK_TYPE_I8
&& type2
== STACK_TYPE_I4
) {
212 ADD_CODE(td
, MINT_CONV_I8_I4_SP
);
213 td
->in_offsets
[td
->ip
- td
->il_code
]++;
214 } else if (type1
!= type2
) {
215 g_warning("%s.%s: branch type mismatch %d %d",
216 td
->method
->klass
->name
, td
->method
->name
,
217 td
->sp
[-1].type
, td
->sp
[-2].type
);
220 handle_branch (td
, short_op
, long_op
, offset
);
224 unary_arith_op(TransformData
*td
, int mint_op
)
226 int op
= mint_op
+ td
->sp
[-1].type
- STACK_TYPE_I4
;
232 binary_arith_op(TransformData
*td
, int mint_op
)
234 int type1
= td
->sp
[-2].type
;
235 int type2
= td
->sp
[-1].type
;
237 #if SIZEOF_VOID_P == 8
238 if ((type1
== STACK_TYPE_MP
|| type1
== STACK_TYPE_I8
) && type2
== STACK_TYPE_I4
) {
239 ADD_CODE(td
, MINT_CONV_I8_I4
);
240 type2
= STACK_TYPE_I8
;
242 if (type1
== STACK_TYPE_I4
&& (type2
== STACK_TYPE_MP
|| type2
== STACK_TYPE_I8
)) {
243 ADD_CODE(td
, MINT_CONV_I8_I4_SP
);
244 type1
= STACK_TYPE_I8
;
245 td
->sp
[-2].type
= STACK_TYPE_I8
;
248 if (type1
== STACK_TYPE_MP
)
249 type1
= STACK_TYPE_I
;
250 if (type2
== STACK_TYPE_MP
)
251 type2
= STACK_TYPE_I
;
252 if (type1
!= type2
) {
253 g_warning("%s.%s: %04x arith type mismatch %s %d %d",
254 td
->method
->klass
->name
, td
->method
->name
,
255 td
->ip
- td
->il_code
, mono_interp_opname
[mint_op
], type1
, type2
);
257 op
= mint_op
+ type1
- STACK_TYPE_I4
;
264 binary_int_op(TransformData
*td
, int mint_op
)
266 int op
= mint_op
+ td
->sp
[-1].type
- STACK_TYPE_I4
;
268 if (td
->sp
[-1].type
!= td
->sp
[-2].type
)
269 g_warning("%s.%s: int type mismatch", td
->method
->klass
->name
, td
->method
->name
);
275 shift_op(TransformData
*td
, int mint_op
)
277 int op
= mint_op
+ td
->sp
[-2].type
- STACK_TYPE_I4
;
279 if (td
->sp
[-1].type
!= STACK_TYPE_I4
) {
280 g_warning("%s.%s: shift type mismatch %d",
281 td
->method
->klass
->name
, td
->method
->name
,
289 mint_type(MonoType
*type
)
294 switch (type
->type
) {
298 case MONO_TYPE_BOOLEAN
:
310 #if SIZEOF_VOID_P == 4
324 case MONO_TYPE_STRING
:
325 case MONO_TYPE_SZARRAY
:
326 case MONO_TYPE_CLASS
:
327 case MONO_TYPE_OBJECT
:
328 case MONO_TYPE_ARRAY
:
330 case MONO_TYPE_VALUETYPE
:
331 if (type
->data
.klass
->enumtype
) {
332 type
= mono_class_enum_basetype (type
->data
.klass
);
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
;
439 if (n
== 0 && mono_method_signature (td
->method
)->hasthis
) {
440 if (td
->method
->klass
->valuetype
)
444 klass
= td
->method
->klass
;
446 ADD_CODE(td
, MINT_LDTHIS
);
449 n
-= mono_method_signature (td
->method
)->hasthis
;
450 type
= mono_method_signature (td
->method
)->params
[n
];
451 mt
= mint_type (type
);
452 if (mt
== MINT_TYPE_VT
) {
454 if (mono_method_signature (td
->method
)->pinvoke
)
455 size
= mono_class_native_size (type
->data
.klass
, NULL
);
457 size
= mono_class_value_size (type
->data
.klass
, NULL
);
459 ADD_CODE(td
, MINT_LDARG_VT
);
460 ADD_CODE(td
, td
->rtm
->arg_offsets
[n
]); /* FIX for large offset */
462 klass
= type
->data
.klass
;
464 ADD_CODE(td
, MINT_LDARG_I1
+ (mt
- MINT_TYPE_I1
));
465 ADD_CODE(td
, td
->rtm
->arg_offsets
[n
]); /* FIX for large offset */
466 if (mt
== MINT_TYPE_O
)
467 klass
= mono_class_from_mono_type (type
);
470 PUSH_TYPE(td
, stack_type
[mt
], klass
);
474 store_arg(TransformData
*td
, int n
)
478 if (n
== 0 && mono_method_signature (td
->method
)->hasthis
)
479 ADD_CODE(td
, MINT_STTHIS
);
482 n
-= mono_method_signature (td
->method
)->hasthis
;
483 type
= mono_method_signature (td
->method
)->params
[n
];
484 mt
= mint_type (type
);
485 if (mt
== MINT_TYPE_VT
) {
487 if (mono_method_signature (td
->method
)->pinvoke
)
488 size
= mono_class_native_size (type
->data
.klass
, NULL
);
490 size
= mono_class_value_size (type
->data
.klass
, NULL
);
491 ADD_CODE(td
, MINT_STARG_VT
);
494 if (td
->sp
[-1].type
== STACK_TYPE_VT
)
497 ADD_CODE(td
, MINT_STARG_I1
+ (mt
- MINT_TYPE_I1
));
498 ADD_CODE(td
, td
->rtm
->arg_offsets
[n
]);
505 store_inarg(TransformData
*td
, int n
)
507 MonoType
*type
= mono_method_signature (td
->method
)->params
[n
];
508 int mt
= mint_type (type
);
509 if (mt
== MINT_TYPE_VT
) {
511 if (mono_method_signature (td
->method
)->pinvoke
)
512 size
= mono_class_native_size (type
->data
.klass
, NULL
);
514 size
= mono_class_value_size (type
->data
.klass
, NULL
);
515 ADD_CODE(td
, MINT_STINARG_VT
);
519 ADD_CODE(td
, MINT_STINARG_I1
+ (mt
- MINT_TYPE_I1
));
525 load_local(TransformData
*td
, int n
)
527 MonoType
*type
= td
->header
->locals
[n
];
528 int mt
= mint_type (type
);
529 int offset
= td
->rtm
->local_offsets
[n
];
530 MonoClass
*klass
= NULL
;
531 if (mt
== MINT_TYPE_VT
) {
532 gint32 size
= mono_class_value_size (type
->data
.klass
, NULL
);
534 ADD_CODE(td
, MINT_LDLOC_VT
);
535 ADD_CODE(td
, offset
); /*FIX for large offset */
537 klass
= type
->data
.klass
;
539 if (mt
== MINT_TYPE_I4
&& !td
->is_bb_start
[td
->in_start
- td
->il_code
] && td
->last_new_ip
!= NULL
&&
540 td
->last_new_ip
[0] == MINT_STLOC_I4
&& td
->last_new_ip
[1] == offset
) {
541 td
->last_new_ip
[0] = MINT_STLOC_NP_I4
;
542 } else if (mt
== MINT_TYPE_O
&& !td
->is_bb_start
[td
->in_start
- td
->il_code
] && td
->last_new_ip
!= NULL
&&
543 td
->last_new_ip
[0] == MINT_STLOC_O
&& td
->last_new_ip
[1] == offset
) {
544 td
->last_new_ip
[0] = MINT_STLOC_NP_O
;
546 ADD_CODE(td
, MINT_LDLOC_I1
+ (mt
- MINT_TYPE_I1
));
547 ADD_CODE(td
, offset
); /*FIX for large offset */
549 if (mt
== MINT_TYPE_O
)
550 klass
= mono_class_from_mono_type (type
);
552 PUSH_TYPE(td
, stack_type
[mt
], klass
);
556 store_local(TransformData
*td
, int n
)
558 MonoType
*type
= td
->header
->locals
[n
];
559 int mt
= mint_type (type
);
560 int offset
= td
->rtm
->local_offsets
[n
];
562 #if SIZEOF_VOID_P == 8
563 if (td
->sp
[-1].type
== STACK_TYPE_I4
&& stack_type
[mt
] == STACK_TYPE_I8
) {
564 ADD_CODE(td
, MINT_CONV_I8_I4
);
565 td
->sp
[-1].type
= STACK_TYPE_I8
;
568 if (!can_store(td
->sp
[-1].type
, stack_type
[mt
])) {
569 g_warning("%s.%s: Store local stack type mismatch %d %d",
570 td
->method
->klass
->name
, td
->method
->name
,
571 stack_type
[mt
], td
->sp
[-1].type
);
573 if (mt
== MINT_TYPE_VT
) {
574 gint32 size
= mono_class_value_size (type
->data
.klass
, NULL
);
575 ADD_CODE(td
, MINT_STLOC_VT
);
576 ADD_CODE(td
, offset
); /*FIX for large offset */
578 if (td
->sp
[-1].type
== STACK_TYPE_VT
)
581 ADD_CODE(td
, MINT_STLOC_I1
+ (mt
- MINT_TYPE_I1
));
582 ADD_CODE(td
, offset
); /*FIX for large offset */
587 #define SIMPLE_OP(td, op) \
594 get_data_item_index (TransformData
*td
, void *ptr
)
596 gpointer p
= g_hash_table_lookup (td
->data_hash
, ptr
);
599 return GPOINTER_TO_UINT (p
) - 1;
600 if (td
->max_data_items
== td
->n_data_items
) {
601 td
->max_data_items
= td
->n_data_items
== 0 ? 16 : 2 * td
->max_data_items
;
602 td
->data_items
= g_realloc (td
->data_items
, td
->max_data_items
* sizeof(td
->data_items
[0]));
604 index
= td
->n_data_items
;
605 td
->data_items
[index
] = ptr
;
607 g_hash_table_insert (td
->data_hash
, ptr
, GUINT_TO_POINTER (index
+ 1));
612 generate (MonoMethod
*method
, RuntimeMethod
*rtm
, unsigned char *is_bb_start
)
614 MonoMethodHeader
*header
= mono_method_get_header (method
);
615 MonoMethodSignature
*signature
= mono_method_signature (method
);
616 MonoImage
*image
= method
->klass
->image
;
617 MonoDomain
*domain
= mono_domain_get ();
618 MonoGenericContext
*generic_context
= NULL
;
624 MonoClassField
*field
;
625 const unsigned char *end
;
626 int new_in_start_offset
;
627 int body_start_offset
;
631 int generating_code
= 1;
633 if (mono_method_signature (method
)->is_inflated
)
634 generic_context
= &((MonoMethodInflated
*) method
)->context
;
636 memset(&td
, 0, sizeof(td
));
639 td
.is_bb_start
= is_bb_start
;
640 td
.il_code
= header
->code
;
641 td
.code_size
= header
->code_size
;
643 td
.max_code_size
= td
.code_size
;
644 td
.new_code
= (unsigned short *)g_malloc(td
.max_code_size
* sizeof(gushort
));
645 td
.new_code_end
= td
.new_code
+ td
.max_code_size
;
646 td
.in_offsets
= g_malloc0(header
->code_size
* sizeof(int));
647 td
.forward_refs
= g_malloc(header
->code_size
* sizeof(int));
648 td
.stack_state
= g_malloc0(header
->code_size
* sizeof(StackInfo
*));
649 td
.stack_height
= g_malloc(header
->code_size
* sizeof(int));
650 td
.vt_stack_size
= g_malloc(header
->code_size
* sizeof(int));
652 td
.max_data_items
= 0;
653 td
.data_items
= NULL
;
654 td
.data_hash
= g_hash_table_new (NULL
, NULL
);
655 rtm
->data_items
= td
.data_items
;
656 for (i
= 0; i
< header
->code_size
; i
++) {
657 td
.forward_refs
[i
] = -1;
658 td
.stack_height
[i
] = -1;
660 td
.new_ip
= td
.new_code
;
661 td
.last_new_ip
= NULL
;
663 td
.stack
= g_malloc0(header
->max_stack
* sizeof(td
.stack
[0]));
665 td
.max_stack_height
= 0;
667 for (i
= 0; i
< header
->num_clauses
; i
++) {
668 MonoExceptionClause
*c
= header
->clauses
+ i
;
669 td
.stack_height
[c
->handler_offset
] = 0;
670 td
.vt_stack_size
[c
->handler_offset
] = 0;
671 td
.is_bb_start
[c
->handler_offset
] = 1;
672 if (c
->flags
== MONO_EXCEPTION_CLAUSE_NONE
) {
673 td
.stack_height
[c
->handler_offset
] = 1;
674 td
.stack_state
[c
->handler_offset
] = g_malloc0(sizeof(StackInfo
));
675 td
.stack_state
[c
->handler_offset
][0].type
= STACK_TYPE_O
;
676 td
.stack_state
[c
->handler_offset
][0].klass
= NULL
; /*FIX*/
680 td
.ip
= header
->code
;
681 end
= td
.ip
+ header
->code_size
;
683 if (mono_interp_traceopt
) {
684 char *tmp
= mono_disasm_code (NULL
, method
, td
.ip
, end
);
685 char *name
= mono_method_full_name (method
, TRUE
);
686 g_print ("Method %s, original code:\n", name
);
687 g_print ("%s\n", tmp
);
692 for (i
= 0; i
< signature
->param_count
; i
++)
695 body_start_offset
= td
.new_ip
- td
.new_code
;
697 for (i
= 0; i
< header
->num_locals
; i
++) {
698 int mt
= mint_type(header
->locals
[i
]);
699 if (mt
== MINT_TYPE_VT
|| mt
== MINT_TYPE_O
) {
700 ADD_CODE(&td
, MINT_INITLOCALS
);
705 while (td
.ip
< end
) {
708 g_assert (td
.sp
>= td
.stack
);
709 g_assert (td
.vt_sp
< 0x10000000);
710 in_offset
= td
.ip
- header
->code
;
711 td
.in_offsets
[in_offset
] = td
.new_ip
- td
.new_code
;
712 new_in_start_offset
= td
.new_ip
- td
.new_code
;
714 while (td
.forward_refs
[in_offset
] >= 0) {
715 int j
= td
.forward_refs
[in_offset
];
717 td
.forward_refs
[in_offset
] = td
.forward_refs
[j
];
718 if (td
.in_offsets
[j
] < 0) {
719 int old_switch_offset
= -td
.in_offsets
[j
];
720 int new_switch_offset
= td
.in_offsets
[old_switch_offset
];
721 int switch_case
= (j
- old_switch_offset
- 5) / 4;
722 int n_cases
= read32 (header
->code
+ old_switch_offset
+ 1);
723 offset
= (td
.new_ip
- td
.new_code
) - (new_switch_offset
+ 2 * n_cases
+ 3);
724 slot
= new_switch_offset
+ 3 + 2 * switch_case
;
725 td
.new_code
[slot
] = * (unsigned short *)(&offset
);
726 td
.new_code
[slot
+ 1] = * ((unsigned short *)&offset
+ 1);
728 int op
= td
.new_code
[td
.in_offsets
[j
]];
729 if (mono_interp_opargtype
[op
] == MintOpShortBranch
) {
730 offset
= (td
.new_ip
- td
.new_code
) - td
.in_offsets
[j
];
731 g_assert (offset
<= 32767);
732 slot
= td
.in_offsets
[j
] + 1;
733 td
.new_code
[slot
] = offset
;
735 offset
= (td
.new_ip
- td
.new_code
) - td
.in_offsets
[j
];
736 slot
= td
.in_offsets
[j
] + 1;
737 td
.new_code
[slot
] = * (unsigned short *)(&offset
);
738 td
.new_code
[slot
+ 1] = * ((unsigned short *)&offset
+ 1);
742 if (td
.stack_height
[in_offset
] >= 0) {
743 g_assert (is_bb_start
[in_offset
]);
744 if (td
.stack_height
[in_offset
] > 0)
745 memcpy (td
.stack
, td
.stack_state
[in_offset
], td
.stack_height
[in_offset
] * sizeof(td
.stack
[0]));
746 td
.sp
= td
.stack
+ td
.stack_height
[in_offset
];
747 td
.vt_sp
= td
.vt_stack_size
[in_offset
];
749 if (is_bb_start
[in_offset
]) {
752 if (!generating_code
) {
753 while (td
.ip
< end
&& !is_bb_start
[td
.ip
- td
.il_code
])
757 if (mono_interp_traceopt
> 1) {
758 printf("IL_%04lx %s %-10s -> IL_%04lx, sp %ld, %s %-12s vt_sp %u (max %u)\n",
760 td
.is_bb_start
[td
.ip
- td
.il_code
] == 3 ? "<>" :
761 td
.is_bb_start
[td
.ip
- td
.il_code
] == 2 ? "< " :
762 td
.is_bb_start
[td
.ip
- td
.il_code
] == 1 ? " >" : " ",
763 mono_opcode_name (*td
.ip
), td
.new_ip
- td
.new_code
, td
.sp
- td
.stack
,
764 td
.sp
> td
.stack
? stack_type_string
[td
.sp
[-1].type
] : " ",
765 (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
) : "",
766 td
.vt_sp
, td
.max_vt_sp
);
774 SIMPLE_OP(td
, MINT_BREAK
);
780 load_arg (&td
, *td
.ip
- CEE_LDARG_0
);
787 load_local (&td
, *td
.ip
- CEE_LDLOC_0
);
794 store_local (&td
, *td
.ip
- CEE_STLOC_0
);
798 load_arg (&td
, ((guint8
*)td
.ip
)[1]);
802 int n
= ((guint8
*)td
.ip
)[1];
803 if (n
== 0 && signature
->hasthis
)
804 ADD_CODE(&td
, MINT_LDTHISA
);
806 ADD_CODE(&td
, MINT_LDARGA
);
807 ADD_CODE(&td
, td
.rtm
->arg_offsets
[n
- signature
->hasthis
]);
809 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_MP
);
814 store_arg (&td
, ((guint8
*)td
.ip
)[1]);
818 load_local (&td
, ((guint8
*)td
.ip
)[1]);
822 ADD_CODE(&td
, MINT_LDLOCA_S
);
823 ADD_CODE(&td
, td
.rtm
->local_offsets
[((guint8
*)td
.ip
)[1]]);
824 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_MP
);
828 store_local (&td
, ((guint8
*)td
.ip
)[1]);
832 SIMPLE_OP(td
, MINT_LDNULL
);
833 PUSH_TYPE(&td
, STACK_TYPE_O
, NULL
);
836 SIMPLE_OP(td
, MINT_LDC_I4_M1
);
837 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I4
);
840 if (!td
.is_bb_start
[td
.ip
+ 1 - td
.il_code
] && td
.ip
[1] == 0xfe && td
.ip
[2] == CEE_CEQ
&&
841 td
.sp
> td
.stack
&& td
.sp
[-1].type
== STACK_TYPE_I4
) {
842 SIMPLE_OP(td
, MINT_CEQ0_I4
);
845 SIMPLE_OP(td
, MINT_LDC_I4_0
);
846 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I4
);
850 if (!td
.is_bb_start
[td
.ip
+ 1 - td
.il_code
] &&
851 (td
.ip
[1] == CEE_ADD
|| td
.ip
[1] == CEE_SUB
) && td
.sp
[-1].type
== STACK_TYPE_I4
) {
852 ADD_CODE(&td
, td
.ip
[1] == CEE_ADD
? MINT_ADD1_I4
: MINT_SUB1_I4
);
855 SIMPLE_OP(td
, MINT_LDC_I4_1
);
856 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I4
);
866 SIMPLE_OP(td
, (*td
.ip
- CEE_LDC_I4_0
) + MINT_LDC_I4_0
);
867 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I4
);
870 ADD_CODE(&td
, MINT_LDC_I4_S
);
871 ADD_CODE(&td
, ((gint8
*) td
.ip
) [1]);
873 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I4
);
876 i32
= read32 (td
.ip
+ 1);
877 ADD_CODE(&td
, MINT_LDC_I4
);
880 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I4
);
883 gint64 val
= read64 (td
.ip
+ 1);
884 ADD_CODE(&td
, MINT_LDC_I8
);
887 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I8
);
892 readr4 (td
.ip
+ 1, &val
);
893 ADD_CODE(&td
, MINT_LDC_R4
);
896 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_R8
);
901 readr8 (td
.ip
+ 1, &val
);
902 ADD_CODE(&td
, MINT_LDC_R8
);
905 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_R8
);
909 int type
= td
.sp
[-1].type
;
910 MonoClass
*klass
= td
.sp
[-1].klass
;
911 if (td
.sp
[-1].type
== STACK_TYPE_VT
) {
912 gint32 size
= mono_class_value_size (klass
, NULL
);
914 ADD_CODE(&td
, MINT_DUP_VT
);
918 SIMPLE_OP(td
, MINT_DUP
);
919 PUSH_TYPE(&td
, type
, klass
);
924 SIMPLE_OP(td
, MINT_POP
);
925 if (td
.sp
[-1].type
== STACK_TYPE_VT
) {
926 int size
= mono_class_value_size (td
.sp
[-1].klass
, NULL
);
927 size
= (size
+ 7) & ~7;
928 ADD_CODE(&td
, MINT_VTRESULT
);
937 if (td
.sp
> td
.stack
)
938 g_warning ("CEE_JMP: stack must be empty");
939 token
= read32 (td
.ip
+ 1);
940 m
= mono_get_method_full (image
, token
, NULL
, generic_context
);
941 ADD_CODE (&td
, MINT_JMP
);
942 ADD_CODE (&td
, get_data_item_index (&td
, mono_interp_get_runtime_method (domain
, m
, &error
)));
943 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
947 case CEE_CALLVIRT
: /* Fall through */
948 case CEE_CALLI
: /* Fall through */
951 MonoMethodSignature
*csignature
;
952 int virtual = *td
.ip
== CEE_CALLVIRT
;
953 int calli
= *td
.ip
== CEE_CALLI
;
955 guint32 vt_stack_used
= 0;
956 guint32 vt_res_size
= 0;
961 token
= read32 (td
.ip
+ 1);
964 native
= (method
->wrapper_type
!= MONO_WRAPPER_DELEGATE_INVOKE
&& td
.sp
[-1].type
== STACK_TYPE_I
);
966 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
967 csignature
= (MonoMethodSignature
*)mono_method_get_wrapper_data (method
, token
);
969 csignature
= mono_metadata_parse_signature (image
, token
);
972 if (method
->wrapper_type
== MONO_WRAPPER_NONE
)
973 m
= mono_get_method_full (image
, token
, NULL
, generic_context
);
975 m
= (MonoMethod
*)mono_method_get_wrapper_data (method
, token
);
976 csignature
= mono_method_signature (m
);
977 if (m
->klass
== mono_defaults
.string_class
) {
978 if (m
->name
[0] == 'g') {
979 if (strcmp (m
->name
, "get_Chars") == 0)
981 else if (strcmp (m
->name
, "get_Length") == 0)
984 } else if (m
->klass
== mono_defaults
.array_class
) {
985 if (strcmp (m
->name
, "get_Rank") == 0)
986 op
= MINT_ARRAY_RANK
;
987 else if (strcmp (m
->name
, "get_Length") == 0)
991 CHECK_STACK(&td
, csignature
->param_count
+ csignature
->hasthis
);
992 if (!calli
&& (!virtual || (m
->flags
& METHOD_ATTRIBUTE_VIRTUAL
) == 0) &&
993 (m
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) == 0 &&
994 (m
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) == 0) {
995 int called_inited
= mono_class_vtable (domain
, m
->klass
)->initialized
;
996 MonoMethodHeader
*mheader
= mono_method_get_header (m
);
998 if (/*mono_metadata_signature_equal (method->signature, m->signature) */ method
== m
&& *(td
.ip
+ 5) == CEE_RET
) {
1000 if (mono_interp_traceopt
)
1001 g_print ("Optimize tail call of %s.%s\n", m
->klass
->name
, m
->name
);
1002 for (i
= csignature
->param_count
- 1; i
>= 0; --i
)
1003 store_arg (&td
, i
+ csignature
->hasthis
);
1005 if (csignature
->hasthis
) {
1006 ADD_CODE(&td
, MINT_STTHIS
);
1009 ADD_CODE(&td
, MINT_BR_S
);
1010 offset
= body_start_offset
- ((td
.new_ip
- 1) - td
.new_code
);
1011 ADD_CODE(&td
, offset
);
1012 if (!is_bb_start
[td
.ip
+ 5 - td
.il_code
])
1013 ++td
.ip
; /* gobble the CEE_RET if it isn't branched to */
1017 /* mheader might not exist if this is a delegate invoc, etc */
1018 if (mheader
&& *mheader
->code
== CEE_RET
&& called_inited
) {
1019 if (mono_interp_traceopt
)
1020 g_print ("Inline (empty) call of %s.%s\n", m
->klass
->name
, m
->name
);
1021 for (i
= 0; i
< csignature
->param_count
; i
++)
1022 ADD_CODE(&td
, MINT_POP
); /*FIX: vt */
1023 if (csignature
->hasthis
) {
1025 ADD_CODE(&td
, MINT_CKNULL
);
1026 ADD_CODE(&td
, MINT_POP
);
1028 td
.sp
-= csignature
->param_count
+ csignature
->hasthis
;
1034 if (method
->wrapper_type
== MONO_WRAPPER_NONE
&& m
!= NULL
) {
1035 if (m
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
)
1036 m
= mono_marshal_get_native_wrapper (m
, FALSE
, FALSE
);
1037 if (!virtual && m
->iflags
& METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED
)
1038 m
= mono_marshal_get_synchronized_wrapper (m
);
1040 g_assert (csignature
->call_convention
== MONO_CALL_DEFAULT
|| csignature
->call_convention
== MONO_CALL_C
);
1041 td
.sp
-= csignature
->param_count
+ csignature
->hasthis
;
1042 for (i
= 0; i
< csignature
->param_count
; ++i
) {
1043 if (td
.sp
[i
+ csignature
->hasthis
].type
== STACK_TYPE_VT
) {
1045 if (csignature
->pinvoke
&& method
->wrapper_type
!= MONO_WRAPPER_NONE
)
1046 size
= mono_class_native_size (csignature
->params
[i
]->data
.klass
, NULL
);
1048 size
= mono_class_value_size (csignature
->params
[i
]->data
.klass
, NULL
);
1049 size
= (size
+ 7) & ~7;
1050 vt_stack_used
+= size
;
1054 /* need to handle typedbyref ... */
1055 if (csignature
->ret
->type
!= MONO_TYPE_VOID
) {
1056 int mt
= mint_type(csignature
->ret
);
1057 MonoClass
*klass
= NULL
;
1058 if (mt
== MINT_TYPE_VT
) {
1059 if (csignature
->pinvoke
&& method
->wrapper_type
!= MONO_WRAPPER_NONE
)
1060 vt_res_size
= mono_class_native_size (csignature
->ret
->data
.klass
, NULL
);
1062 vt_res_size
= mono_class_value_size (csignature
->ret
->data
.klass
, NULL
);
1063 PUSH_VT(&td
, vt_res_size
);
1064 klass
= csignature
->ret
->data
.klass
;
1065 } else if (mt
== MINT_TYPE_O
)
1066 klass
= mono_class_from_mono_type (csignature
->ret
);
1067 PUSH_TYPE(&td
, stack_type
[mt
], klass
);
1073 #if SIZEOF_VOID_P == 8
1074 if (op
== MINT_LDLEN
)
1075 ADD_CODE(&td
, MINT_CONV_I4_I8
);
1079 ADD_CODE(&td
, native
? MINT_CALLI_NAT
: MINT_CALLI
);
1081 ADD_CODE(&td
, is_void
? MINT_VCALLVIRT
: MINT_CALLVIRT
);
1083 ADD_CODE(&td
, is_void
? MINT_VCALL
: MINT_CALL
);
1084 ADD_CODE(&td
, get_data_item_index (&td
, calli
? (void *)csignature
: (void *)mono_interp_get_runtime_method (domain
, m
, &error
)));
1085 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
1088 if (vt_stack_used
!= 0 || vt_res_size
!= 0) {
1089 ADD_CODE(&td
, MINT_VTRESULT
);
1090 ADD_CODE(&td
, vt_res_size
);
1091 WRITE32(&td
, &vt_stack_used
);
1092 td
.vt_sp
-= vt_stack_used
;
1098 if (signature
->ret
->type
!= MONO_TYPE_VOID
) {
1100 if (mint_type(signature
->ret
) == MINT_TYPE_VT
) {
1101 vt_size
= mono_class_value_size (signature
->ret
->data
.klass
, NULL
);
1102 vt_size
= (vt_size
+ 7) & ~7;
1105 if (td
.sp
> td
.stack
)
1106 g_warning ("%s.%s: CEE_RET: more values on stack: %d", td
.method
->klass
->name
, td
.method
->name
, td
.sp
- td
.stack
);
1107 if (td
.vt_sp
!= vt_size
)
1108 g_warning ("%s.%s: CEE_RET: value type stack: %d", td
.method
->klass
->name
, td
.method
->name
, td
.vt_sp
);
1110 SIMPLE_OP(td
, signature
->ret
->type
== MONO_TYPE_VOID
? MINT_RET_VOID
: MINT_RET
);
1112 ADD_CODE(&td
, MINT_RET_VT
);
1113 WRITE32(&td
, &vt_size
);
1116 generating_code
= 0;
1120 handle_branch (&td
, MINT_BR_S
, MINT_BR
, 5 + read32 (td
.ip
+ 1));
1122 generating_code
= 0;
1125 handle_branch (&td
, MINT_BR_S
, MINT_BR
, 2 + (gint8
)td
.ip
[1]);
1127 generating_code
= 0;
1130 one_arg_branch (&td
, MINT_BRFALSE_I4
, 5 + read32 (td
.ip
+ 1));
1134 one_arg_branch (&td
, MINT_BRFALSE_I4
, 2 + (gint8
)td
.ip
[1]);
1138 one_arg_branch (&td
, MINT_BRTRUE_I4
, 5 + read32 (td
.ip
+ 1));
1142 one_arg_branch (&td
, MINT_BRTRUE_I4
, 2 + (gint8
)td
.ip
[1]);
1146 two_arg_branch (&td
, MINT_BEQ_I4
, 5 + read32 (td
.ip
+ 1));
1150 two_arg_branch (&td
, MINT_BEQ_I4
, 2 + (gint8
) td
.ip
[1]);
1154 two_arg_branch (&td
, MINT_BGE_I4
, 5 + read32 (td
.ip
+ 1));
1158 two_arg_branch (&td
, MINT_BGE_I4
, 2 + (gint8
) td
.ip
[1]);
1162 two_arg_branch (&td
, MINT_BGT_I4
, 5 + read32 (td
.ip
+ 1));
1166 two_arg_branch (&td
, MINT_BGT_I4
, 2 + (gint8
) td
.ip
[1]);
1170 two_arg_branch (&td
, MINT_BLT_I4
, 5 + read32 (td
.ip
+ 1));
1174 two_arg_branch (&td
, MINT_BLT_I4
, 2 + (gint8
) td
.ip
[1]);
1178 two_arg_branch (&td
, MINT_BLE_I4
, 5 + read32 (td
.ip
+ 1));
1182 two_arg_branch (&td
, MINT_BLE_I4
, 2 + (gint8
) td
.ip
[1]);
1186 two_arg_branch (&td
, MINT_BNE_UN_I4
, 5 + read32 (td
.ip
+ 1));
1190 two_arg_branch (&td
, MINT_BNE_UN_I4
, 2 + (gint8
) td
.ip
[1]);
1194 two_arg_branch (&td
, MINT_BGE_UN_I4
, 5 + read32 (td
.ip
+ 1));
1198 two_arg_branch (&td
, MINT_BGE_UN_I4
, 2 + (gint8
) td
.ip
[1]);
1202 two_arg_branch (&td
, MINT_BGT_UN_I4
, 5 + read32 (td
.ip
+ 1));
1206 two_arg_branch (&td
, MINT_BGT_UN_I4
, 2 + (gint8
) td
.ip
[1]);
1210 two_arg_branch (&td
, MINT_BLE_UN_I4
, 5 + read32 (td
.ip
+ 1));
1214 two_arg_branch (&td
, MINT_BLE_UN_I4
, 2 + (gint8
) td
.ip
[1]);
1218 two_arg_branch (&td
, MINT_BLT_UN_I4
, 5 + read32 (td
.ip
+ 1));
1222 two_arg_branch (&td
, MINT_BLT_UN_I4
, 2 + (gint8
) td
.ip
[1]);
1227 const unsigned char *next_ip
;
1228 const unsigned char *base_ip
= td
.ip
;
1229 unsigned short *next_new_ip
;
1232 ADD_CODE(&td
, MINT_SWITCH
);
1233 ADD_CODE(&td
, * (unsigned short *)(&n
));
1234 ADD_CODE(&td
, * ((unsigned short *)&n
+ 1));
1236 next_ip
= td
.ip
+ n
* 4;
1237 next_new_ip
= td
.new_ip
+ n
* 2;
1238 for (i
= 0; i
< n
; i
++) {
1239 offset
= read32 (td
.ip
);
1240 target
= next_ip
- td
.il_code
+ offset
;
1242 target
= td
.in_offsets
[target
] - (next_new_ip
- td
.new_code
);
1244 int prev
= td
.forward_refs
[target
];
1245 td
.forward_refs
[td
.ip
- td
.il_code
] = prev
;
1246 td
.forward_refs
[target
] = td
.ip
- td
.il_code
;
1247 td
.in_offsets
[td
.ip
- td
.il_code
] = - (base_ip
- td
.il_code
);
1249 ADD_CODE(&td
, * (unsigned short *)(&target
));
1250 ADD_CODE(&td
, * ((unsigned short *)&target
+ 1));
1257 CHECK_STACK (&td
, 1);
1258 SIMPLE_OP (td
, MINT_LDIND_I1
);
1259 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1262 CHECK_STACK (&td
, 1);
1263 SIMPLE_OP (td
, MINT_LDIND_U1
);
1264 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1267 CHECK_STACK (&td
, 1);
1268 SIMPLE_OP (td
, MINT_LDIND_I2
);
1269 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1272 CHECK_STACK (&td
, 1);
1273 SIMPLE_OP (td
, MINT_LDIND_U2
);
1274 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1277 CHECK_STACK (&td
, 1);
1278 SIMPLE_OP (td
, MINT_LDIND_I4
);
1279 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1282 CHECK_STACK (&td
, 1);
1283 SIMPLE_OP (td
, MINT_LDIND_U4
);
1284 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1287 CHECK_STACK (&td
, 1);
1288 SIMPLE_OP (td
, MINT_LDIND_I8
);
1289 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
1292 CHECK_STACK (&td
, 1);
1293 SIMPLE_OP (td
, MINT_LDIND_I
);
1294 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I
);
1297 CHECK_STACK (&td
, 1);
1298 SIMPLE_OP (td
, MINT_LDIND_R4
);
1299 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
1302 CHECK_STACK (&td
, 1);
1303 SIMPLE_OP (td
, MINT_LDIND_R8
);
1304 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
1307 CHECK_STACK (&td
, 1);
1308 SIMPLE_OP (td
, MINT_LDIND_REF
);
1309 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_O
);
1312 CHECK_STACK (&td
, 2);
1313 SIMPLE_OP (td
, MINT_STIND_REF
);
1317 CHECK_STACK (&td
, 2);
1318 SIMPLE_OP (td
, MINT_STIND_I1
);
1322 CHECK_STACK (&td
, 2);
1323 SIMPLE_OP (td
, MINT_STIND_I2
);
1327 CHECK_STACK (&td
, 2);
1328 SIMPLE_OP (td
, MINT_STIND_I4
);
1332 CHECK_STACK (&td
, 2);
1333 SIMPLE_OP (td
, MINT_STIND_I
);
1337 CHECK_STACK (&td
, 2);
1338 SIMPLE_OP (td
, MINT_STIND_I8
);
1342 CHECK_STACK (&td
, 2);
1343 SIMPLE_OP (td
, MINT_STIND_R4
);
1347 CHECK_STACK (&td
, 2);
1348 SIMPLE_OP (td
, MINT_STIND_R8
);
1352 binary_arith_op(&td
, MINT_ADD_I4
);
1356 binary_arith_op(&td
, MINT_SUB_I4
);
1360 binary_arith_op(&td
, MINT_MUL_I4
);
1364 binary_arith_op(&td
, MINT_DIV_I4
);
1368 binary_arith_op(&td
, MINT_DIV_UN_I4
);
1372 binary_int_op (&td
, MINT_REM_I4
);
1376 binary_int_op (&td
, MINT_REM_UN_I4
);
1380 binary_int_op (&td
, MINT_AND_I4
);
1384 binary_int_op (&td
, MINT_OR_I4
);
1388 binary_int_op (&td
, MINT_XOR_I4
);
1392 shift_op (&td
, MINT_SHL_I4
);
1396 shift_op (&td
, MINT_SHR_I4
);
1400 shift_op (&td
, MINT_SHR_UN_I4
);
1404 unary_arith_op (&td
, MINT_NEG_I4
);
1408 unary_arith_op (&td
, MINT_NOT_I4
);
1412 CHECK_STACK (&td
, 1);
1413 switch (td
.sp
[-1].type
) {
1415 ADD_CODE(&td
, MINT_CONV_U1_R8
);
1418 ADD_CODE(&td
, MINT_CONV_U1_I4
);
1421 ADD_CODE(&td
, MINT_CONV_U1_I8
);
1424 g_assert_not_reached ();
1427 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1430 CHECK_STACK (&td
, 1);
1431 switch (td
.sp
[-1].type
) {
1433 ADD_CODE(&td
, MINT_CONV_I1_R8
);
1436 ADD_CODE(&td
, MINT_CONV_I1_I4
);
1439 ADD_CODE(&td
, MINT_CONV_I1_I8
);
1442 g_assert_not_reached ();
1445 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1448 CHECK_STACK (&td
, 1);
1449 switch (td
.sp
[-1].type
) {
1451 ADD_CODE(&td
, MINT_CONV_U2_R8
);
1454 ADD_CODE(&td
, MINT_CONV_U2_I4
);
1457 ADD_CODE(&td
, MINT_CONV_U2_I8
);
1460 g_assert_not_reached ();
1463 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1466 CHECK_STACK (&td
, 1);
1467 switch (td
.sp
[-1].type
) {
1469 ADD_CODE(&td
, MINT_CONV_I2_R8
);
1472 ADD_CODE(&td
, MINT_CONV_I2_I4
);
1475 ADD_CODE(&td
, MINT_CONV_I2_I8
);
1478 g_assert_not_reached ();
1481 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1484 CHECK_STACK (&td
, 1);
1485 switch (td
.sp
[-1].type
) {
1487 #if SIZEOF_VOID_P == 4
1488 ADD_CODE(&td
, MINT_CONV_U4_R8
);
1490 ADD_CODE(&td
, MINT_CONV_U8_R8
);
1494 #if SIZEOF_VOID_P == 8
1495 ADD_CODE(&td
, MINT_CONV_U8_I4
);
1499 #if SIZEOF_VOID_P == 4
1500 ADD_CODE(&td
, MINT_CONV_U4_I8
);
1504 g_assert_not_reached ();
1507 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I
);
1510 CHECK_STACK (&td
, 1);
1511 switch (td
.sp
[-1].type
) {
1513 #if SIZEOF_VOID_P == 8
1514 ADD_CODE(&td
, MINT_CONV_I8_R8
);
1516 ADD_CODE(&td
, MINT_CONV_I4_R8
);
1520 #if SIZEOF_VOID_P == 8
1521 ADD_CODE(&td
, MINT_CONV_I8_I4
);
1529 #if SIZEOF_VOID_P == 4
1530 ADD_CODE(&td
, MINT_CONV_I4_I8
);
1534 g_assert_not_reached ();
1537 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I
);
1540 CHECK_STACK (&td
, 1);
1541 switch (td
.sp
[-1].type
) {
1543 ADD_CODE(&td
, MINT_CONV_U4_R8
);
1548 ADD_CODE(&td
, MINT_CONV_U4_I8
);
1551 #if SIZEOF_VOID_P == 8
1552 ADD_CODE(&td
, MINT_CONV_U4_I8
);
1556 g_assert_not_reached ();
1559 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1562 CHECK_STACK (&td
, 1);
1563 switch (td
.sp
[-1].type
) {
1565 ADD_CODE(&td
, MINT_CONV_I4_R8
);
1570 ADD_CODE(&td
, MINT_CONV_I4_I8
);
1573 #if SIZEOF_VOID_P == 8
1574 ADD_CODE(&td
, MINT_CONV_I4_I8
);
1578 g_assert_not_reached ();
1581 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
1584 CHECK_STACK (&td
, 1);
1585 switch (td
.sp
[-1].type
) {
1587 ADD_CODE(&td
, MINT_CONV_I8_R8
);
1590 ADD_CODE(&td
, MINT_CONV_I8_I4
);
1595 #if SIZEOF_VOID_P == 4
1596 ADD_CODE(&td
, MINT_CONV_I8_I4
);
1600 g_assert_not_reached ();
1603 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
1606 CHECK_STACK (&td
, 1);
1607 switch (td
.sp
[-1].type
) {
1609 ADD_CODE(&td
, MINT_CONV_R4_R8
);
1612 ADD_CODE(&td
, MINT_CONV_R4_I8
);
1615 ADD_CODE(&td
, MINT_CONV_R4_I4
);
1618 g_assert_not_reached ();
1621 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
1624 CHECK_STACK (&td
, 1);
1625 switch (td
.sp
[-1].type
) {
1627 ADD_CODE(&td
, MINT_CONV_R8_I4
);
1630 ADD_CODE(&td
, MINT_CONV_R8_I8
);
1635 g_assert_not_reached ();
1638 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
1641 CHECK_STACK (&td
, 1);
1642 switch (td
.sp
[-1].type
) {
1644 ADD_CODE(&td
, MINT_CONV_U8_I4
);
1649 ADD_CODE(&td
, MINT_CONV_U8_R8
);
1652 #if SIZEOF_VOID_P == 4
1653 ADD_CODE(&td
, MINT_CONV_U8_I4
);
1657 g_assert_not_reached ();
1660 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
1666 vtklass
= mono_class_get_full (image
, read32 (ip
), generic_context
);
1669 memcpy (sp
[0].data
.p
, sp
[1].data
.p
, mono_class_value_size (vtklass
, NULL
));
1675 CHECK_STACK (&td
, 1);
1677 token
= read32 (td
.ip
+ 1);
1679 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
1680 klass
= (MonoClass
*)mono_method_get_wrapper_data (method
, token
);
1682 klass
= mono_class_get_full (image
, token
, generic_context
);
1684 ADD_CODE(&td
, MINT_LDOBJ
);
1685 ADD_CODE(&td
, get_data_item_index(&td
, klass
));
1686 if (klass
->byval_arg
.type
== MONO_TYPE_VALUETYPE
&& !klass
->byval_arg
.data
.klass
->enumtype
) {
1687 size
= mono_class_value_size (klass
, NULL
);
1691 SET_TYPE(td
.sp
- 1, stack_type
[mint_type(&klass
->byval_arg
)], klass
);
1696 token
= mono_metadata_token_index (read32 (td
.ip
+ 1));
1698 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
) {
1699 s
= mono_string_new_wrapper(
1700 mono_method_get_wrapper_data (method
, token
));
1703 s
= mono_ldstr (domain
, image
, token
);
1704 ADD_CODE(&td
, MINT_LDSTR
);
1705 ADD_CODE(&td
, get_data_item_index (&td
, s
));
1706 PUSH_TYPE(&td
, STACK_TYPE_O
, mono_defaults
.string_class
);
1711 MonoMethodSignature
*csignature
;
1712 guint32 vt_stack_used
= 0;
1713 guint32 vt_res_size
= 0;
1716 token
= read32 (td
.ip
);
1719 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
1720 m
= (MonoMethod
*)mono_method_get_wrapper_data (method
, token
);
1722 m
= mono_get_method_full (image
, token
, NULL
, generic_context
);
1724 csignature
= mono_method_signature (m
);
1726 td
.sp
-= csignature
->param_count
;
1727 ADD_CODE(&td
, MINT_NEWOBJ
);
1728 ADD_CODE(&td
, get_data_item_index (&td
, mono_interp_get_runtime_method (domain
, m
, &error
)));
1729 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
1730 if (klass
->byval_arg
.type
== MONO_TYPE_VALUETYPE
) {
1731 vt_res_size
= mono_class_value_size (klass
, NULL
);
1732 PUSH_VT(&td
, vt_res_size
);
1734 for (i
= 0; i
< csignature
->param_count
; ++i
) {
1735 int mt
= mint_type(csignature
->params
[i
]);
1736 if (mt
== MINT_TYPE_VT
) {
1737 gint32 size
= mono_class_value_size (csignature
->params
[i
]->data
.klass
, NULL
);
1738 size
= (size
+ 7) & ~7;
1739 vt_stack_used
+= size
;
1742 if (vt_stack_used
!= 0 || vt_res_size
!= 0) {
1743 ADD_CODE(&td
, MINT_VTRESULT
);
1744 ADD_CODE(&td
, vt_res_size
);
1745 WRITE32(&td
, &vt_stack_used
);
1746 td
.vt_sp
-= vt_stack_used
;
1748 PUSH_TYPE(&td
, stack_type
[mint_type (&klass
->byval_arg
)], klass
);
1752 CHECK_STACK (&td
, 1);
1753 token
= read32 (td
.ip
+ 1);
1754 klass
= mono_class_get_full (image
, token
, generic_context
);
1755 ADD_CODE(&td
, MINT_CASTCLASS
);
1756 ADD_CODE(&td
, get_data_item_index (&td
, klass
));
1757 td
.sp
[-1].klass
= klass
;
1761 CHECK_STACK (&td
, 1);
1762 token
= read32 (td
.ip
+ 1);
1763 klass
= mono_class_get_full (image
, token
, generic_context
);
1764 ADD_CODE(&td
, MINT_ISINST
);
1765 ADD_CODE(&td
, get_data_item_index (&td
, klass
));
1769 switch (td
.sp
[-1].type
) {
1773 ADD_CODE(&td
, MINT_CONV_R_UN_I8
);
1776 ADD_CODE(&td
, MINT_CONV_R_UN_I4
);
1779 g_assert_not_reached ();
1781 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
1784 case CEE_UNBOX_ANY
: /* let's play a dangerous game, TODO */
1786 CHECK_STACK (&td
, 1);
1787 token
= read32 (td
.ip
+ 1);
1789 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
1790 klass
= (MonoClass
*)mono_method_get_wrapper_data (method
, token
);
1792 klass
= mono_class_get_full (image
, token
, generic_context
);
1794 ADD_CODE(&td
, MINT_UNBOX
);
1795 ADD_CODE(&td
, get_data_item_index (&td
, klass
));
1796 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_MP
);
1800 CHECK_STACK (&td
, 1);
1801 SIMPLE_OP (td
, MINT_THROW
);
1803 generating_code
= 0;
1806 CHECK_STACK (&td
, 1);
1807 token
= read32 (td
.ip
+ 1);
1808 field
= mono_field_from_token (image
, token
, &klass
, generic_context
);
1809 mono_class_init (klass
);
1810 mt
= mint_type(field
->type
);
1811 ADD_CODE(&td
, MINT_LDFLDA
);
1812 ADD_CODE(&td
, klass
->valuetype
? field
->offset
- sizeof(MonoObject
) : field
->offset
);
1814 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_MP
);
1817 CHECK_STACK (&td
, 1);
1818 token
= read32 (td
.ip
+ 1);
1819 field
= mono_field_from_token (image
, token
, &klass
, generic_context
);
1820 mono_class_init (klass
);
1821 mt
= mint_type(field
->type
);
1822 if (klass
->marshalbyref
) {
1823 ADD_CODE(&td
, mt
== MINT_TYPE_VT
? MINT_LDRMFLD_VT
: MINT_LDRMFLD
);
1824 ADD_CODE(&td
, get_data_item_index (&td
, field
));
1826 ADD_CODE(&td
, MINT_LDFLD_I1
+ mt
- MINT_TYPE_I1
);
1827 ADD_CODE(&td
, klass
->valuetype
? field
->offset
- sizeof(MonoObject
) : field
->offset
);
1830 if (mt
== MINT_TYPE_VT
) {
1831 int size
= mono_class_value_size (field
->type
->data
.klass
, NULL
);
1833 WRITE32(&td
, &size
);
1834 klass
= field
->type
->data
.klass
;
1835 } else if (mt
== MINT_TYPE_O
)
1836 klass
= mono_class_from_mono_type (field
->type
);
1838 SET_TYPE(td
.sp
- 1, stack_type
[mt
], klass
);
1842 CHECK_STACK (&td
, 2);
1843 token
= read32 (td
.ip
+ 1);
1844 field
= mono_field_from_token (image
, token
, &klass
, generic_context
);
1845 mono_class_init (klass
);
1846 mt
= mint_type(field
->type
);
1847 if (klass
->marshalbyref
) {
1848 ADD_CODE(&td
, mt
== MINT_TYPE_VT
? MINT_STRMFLD_VT
: MINT_STRMFLD
);
1849 ADD_CODE(&td
, get_data_item_index (&td
, field
));
1851 ADD_CODE(&td
, MINT_STFLD_I1
+ mt
- MINT_TYPE_I1
);
1852 ADD_CODE(&td
, klass
->valuetype
? field
->offset
- sizeof(MonoObject
) : field
->offset
);
1854 if (mt
== MINT_TYPE_VT
) {
1855 int size
= mono_class_value_size (field
->type
->data
.klass
, NULL
);
1857 WRITE32(&td
, &size
);
1863 token
= read32 (td
.ip
+ 1);
1864 field
= mono_field_from_token (image
, token
, &klass
, generic_context
);
1865 ADD_CODE(&td
, MINT_LDSFLDA
);
1866 ADD_CODE(&td
, get_data_item_index (&td
, field
));
1868 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_MP
);
1871 token
= read32 (td
.ip
+ 1);
1872 field
= mono_field_from_token (image
, token
, &klass
, generic_context
);
1873 mt
= mint_type(field
->type
);
1874 ADD_CODE(&td
, mt
== MINT_TYPE_VT
? MINT_LDSFLD_VT
: MINT_LDSFLD
);
1875 ADD_CODE(&td
, get_data_item_index (&td
, field
));
1877 if (mt
== MINT_TYPE_VT
) {
1878 int size
= mono_class_value_size (field
->type
->data
.klass
, NULL
);
1880 WRITE32(&td
, &size
);
1881 klass
= field
->type
->data
.klass
;
1883 if (mt
== MINT_TYPE_O
)
1884 klass
= mono_class_from_mono_type (field
->type
);
1885 if (!domain
->special_static_fields
|| !g_hash_table_lookup (domain
->special_static_fields
, field
)) {
1886 if (mt
== MINT_TYPE_O
)
1887 td
.new_ip
[-2] = MINT_LDSFLD_O
;
1888 else if (mt
== MINT_TYPE_I4
)
1889 td
.new_ip
[-2] = MINT_LDSFLD_I4
;
1891 ADD_CODE(&td
, get_data_item_index (&td
, mono_class_vtable (domain
, field
->parent
)));
1894 PUSH_TYPE(&td
, stack_type
[mt
], klass
);
1897 CHECK_STACK (&td
, 1);
1898 token
= read32 (td
.ip
+ 1);
1899 field
= mono_field_from_token (image
, token
, &klass
, generic_context
);
1900 mt
= mint_type(field
->type
);
1901 ADD_CODE(&td
, mt
== MINT_TYPE_VT
? MINT_STSFLD_VT
: MINT_STSFLD
);
1902 ADD_CODE(&td
, get_data_item_index (&td
, field
));
1903 if (mt
== MINT_TYPE_VT
) {
1904 int size
= mono_class_value_size (field
->type
->data
.klass
, NULL
);
1906 WRITE32(&td
, &size
);
1913 token
= read32 (td
.ip
+ 1);
1915 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
1916 klass
= (MonoClass
*)mono_method_get_wrapper_data (method
, token
);
1918 klass
= mono_class_get_full (image
, token
, generic_context
);
1920 ADD_CODE(&td
, td
.sp
[-1].type
== STACK_TYPE_VT
? MINT_STOBJ_VT
: MINT_STOBJ
);
1921 ADD_CODE(&td
, get_data_item_index (&td
, klass
));
1922 if (td
.sp
[-1].type
== STACK_TYPE_VT
) {
1923 size
= mono_class_value_size (klass
, NULL
);
1924 size
= (size
+ 7) & ~7;
1931 case CEE_CONV_OVF_I_UN
:
1932 CHECK_STACK (&td
, 1);
1933 switch (td
.sp
[-1].type
) {
1935 #if SIZEOF_VOID_P == 8
1936 ADD_CODE(&td
, MINT_CONV_OVF_I8_UN_R8
);
1938 ADD_CODE(&td
, MINT_CONV_OVF_I4_UN_R8
);
1945 #if SIZEOF_VOID_P == 8
1946 ADD_CODE(&td
, MINT_CONV_I8_U4
);
1950 g_assert_not_reached ();
1953 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
1956 case CEE_CONV_OVF_I8_UN
:
1957 CHECK_STACK (&td
, 1);
1958 switch (td
.sp
[-1].type
) {
1960 ADD_CODE(&td
, MINT_CONV_OVF_I8_UN_R8
);
1965 ADD_CODE(&td
, MINT_CONV_I8_U4
);
1968 g_assert_not_reached ();
1971 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
1976 CHECK_STACK (&td
, 1);
1977 token
= read32 (td
.ip
+ 1);
1978 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
1979 klass
= (MonoClass
*)mono_method_get_wrapper_data (method
, token
);
1981 klass
= mono_class_get_full (image
, token
, generic_context
);
1982 g_assert (klass
->valuetype
);
1983 if (klass
->byval_arg
.type
== MONO_TYPE_VALUETYPE
&& !klass
->enumtype
) {
1984 size
= mono_class_value_size (klass
, NULL
);
1985 size
= (size
+ 7) & ~7;
1988 ADD_CODE(&td
, MINT_BOX
);
1989 ADD_CODE(&td
, get_data_item_index (&td
, klass
));
1990 SET_TYPE(td
.sp
- 1, STACK_TYPE_O
, klass
);
1995 CHECK_STACK (&td
, 1);
1996 token
= read32 (td
.ip
+ 1);
1998 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
1999 klass
= (MonoClass
*)mono_method_get_wrapper_data (method
, token
);
2001 klass
= mono_class_get_full (image
, token
, generic_context
);
2003 ADD_CODE(&td
, MINT_NEWARR
);
2004 ADD_CODE(&td
, get_data_item_index (&td
, klass
));
2005 SET_TYPE(td
.sp
- 1, STACK_TYPE_O
, klass
);
2009 CHECK_STACK (&td
, 1);
2010 SIMPLE_OP (td
, MINT_LDLEN
);
2011 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I
);
2014 CHECK_STACK (&td
, 2);
2016 token
= read32 (td
.ip
+ 1);
2018 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
2019 klass
= (MonoClass
*)mono_method_get_wrapper_data (method
, token
);
2021 klass
= mono_class_get_full (image
, token
, generic_context
);
2023 ADD_CODE(&td
, MINT_LDELEMA
);
2024 ADD_CODE(&td
, get_data_item_index (&td
, klass
));
2027 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_MP
);
2030 CHECK_STACK (&td
, 2);
2032 SIMPLE_OP (td
, MINT_LDELEM_I1
);
2034 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2037 CHECK_STACK (&td
, 2);
2039 SIMPLE_OP (td
, MINT_LDELEM_U1
);
2041 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2044 CHECK_STACK (&td
, 2);
2046 SIMPLE_OP (td
, MINT_LDELEM_I2
);
2048 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2051 CHECK_STACK (&td
, 2);
2053 SIMPLE_OP (td
, MINT_LDELEM_U2
);
2055 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2058 CHECK_STACK (&td
, 2);
2060 SIMPLE_OP (td
, MINT_LDELEM_I4
);
2062 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2065 CHECK_STACK (&td
, 2);
2067 SIMPLE_OP (td
, MINT_LDELEM_U4
);
2069 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2072 CHECK_STACK (&td
, 2);
2074 SIMPLE_OP (td
, MINT_LDELEM_I8
);
2076 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
2079 CHECK_STACK (&td
, 2);
2081 SIMPLE_OP (td
, MINT_LDELEM_I
);
2083 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I
);
2086 CHECK_STACK (&td
, 2);
2088 SIMPLE_OP (td
, MINT_LDELEM_R4
);
2090 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
2093 CHECK_STACK (&td
, 2);
2095 SIMPLE_OP (td
, MINT_LDELEM_R8
);
2097 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_R8
);
2099 case CEE_LDELEM_REF
:
2100 CHECK_STACK (&td
, 2);
2102 SIMPLE_OP (td
, MINT_LDELEM_REF
);
2104 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_O
);
2107 CHECK_STACK (&td
, 3);
2109 SIMPLE_OP (td
, MINT_STELEM_I
);
2113 CHECK_STACK (&td
, 3);
2115 SIMPLE_OP (td
, MINT_STELEM_I1
);
2119 CHECK_STACK (&td
, 3);
2121 SIMPLE_OP (td
, MINT_STELEM_I2
);
2125 CHECK_STACK (&td
, 3);
2127 SIMPLE_OP (td
, MINT_STELEM_I4
);
2131 CHECK_STACK (&td
, 3);
2133 SIMPLE_OP (td
, MINT_STELEM_I8
);
2137 CHECK_STACK (&td
, 3);
2139 SIMPLE_OP (td
, MINT_STELEM_R4
);
2143 CHECK_STACK (&td
, 3);
2145 SIMPLE_OP (td
, MINT_STELEM_R8
);
2148 case CEE_STELEM_REF
:
2149 CHECK_STACK (&td
, 3);
2151 SIMPLE_OP (td
, MINT_STELEM_REF
);
2158 case CEE_CONV_OVF_U1
:
2160 case CEE_CONV_OVF_I8
:
2162 #if SIZEOF_VOID_P == 8
2163 case CEE_CONV_OVF_U
:
2165 case CEE_REFANYVAL
: ves_abort(); break;
2168 CHECK_STACK (&td
, 1);
2169 SIMPLE_OP (td
, MINT_CKFINITE
);
2171 case CEE_CONV_OVF_I1
:
2172 case CEE_CONV_OVF_I1_UN
:
2173 CHECK_STACK (&td
, 1);
2174 switch (td
.sp
[-1].type
) {
2176 ADD_CODE(&td
, MINT_CONV_OVF_I1_R8
);
2179 ADD_CODE(&td
, MINT_CONV_OVF_I1_I4
);
2182 ADD_CODE(&td
, MINT_CONV_OVF_I1_I8
);
2185 g_assert_not_reached ();
2188 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2190 case CEE_CONV_OVF_U1
:
2191 case CEE_CONV_OVF_U1_UN
:
2192 CHECK_STACK (&td
, 1);
2193 switch (td
.sp
[-1].type
) {
2195 ADD_CODE(&td
, MINT_CONV_OVF_U1_R8
);
2198 ADD_CODE(&td
, MINT_CONV_OVF_U1_I4
);
2201 ADD_CODE(&td
, MINT_CONV_OVF_U1_I8
);
2204 g_assert_not_reached ();
2207 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2209 case CEE_CONV_OVF_I2
:
2210 case CEE_CONV_OVF_I2_UN
:
2211 CHECK_STACK (&td
, 1);
2212 switch (td
.sp
[-1].type
) {
2214 ADD_CODE(&td
, MINT_CONV_OVF_I2_R8
);
2217 ADD_CODE(&td
, MINT_CONV_OVF_I2_I4
);
2220 ADD_CODE(&td
, MINT_CONV_OVF_I2_I8
);
2223 g_assert_not_reached ();
2226 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2228 case CEE_CONV_OVF_U2_UN
:
2229 case CEE_CONV_OVF_U2
:
2230 CHECK_STACK (&td
, 1);
2231 switch (td
.sp
[-1].type
) {
2233 ADD_CODE(&td
, MINT_CONV_OVF_U2_R8
);
2236 ADD_CODE(&td
, MINT_CONV_OVF_U2_I4
);
2239 ADD_CODE(&td
, MINT_CONV_OVF_U2_I8
);
2242 g_assert_not_reached ();
2245 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2247 #if SIZEOF_VOID_P == 4
2248 case CEE_CONV_OVF_I
:
2250 case CEE_CONV_OVF_I4
:
2251 case CEE_CONV_OVF_I4_UN
:
2252 CHECK_STACK (&td
, 1);
2253 switch (td
.sp
[-1].type
) {
2255 ADD_CODE(&td
, MINT_CONV_OVF_I4_R8
);
2258 if (*td
.ip
== CEE_CONV_OVF_I4_UN
)
2259 ADD_CODE(&td
, MINT_CONV_OVF_I4_U4
);
2262 ADD_CODE(&td
, MINT_CONV_OVF_I4_I8
);
2265 g_assert_not_reached ();
2268 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2270 #if SIZEOF_VOID_P == 4
2271 case CEE_CONV_OVF_U
:
2273 case CEE_CONV_OVF_U4
:
2274 case CEE_CONV_OVF_U4_UN
:
2275 CHECK_STACK (&td
, 1);
2276 switch (td
.sp
[-1].type
) {
2278 ADD_CODE(&td
, MINT_CONV_OVF_U4_R8
);
2281 if (*td
.ip
!= CEE_CONV_OVF_U4_UN
)
2282 ADD_CODE(&td
, MINT_CONV_OVF_U4_I4
);
2285 ADD_CODE(&td
, MINT_CONV_OVF_U4_I8
);
2288 g_assert_not_reached ();
2291 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2293 #if SIZEOF_VOID_P == 8
2294 case CEE_CONV_OVF_I
:
2296 case CEE_CONV_OVF_I8
:
2297 CHECK_STACK (&td
, 1);
2298 switch (td
.sp
[-1].type
) {
2300 ADD_CODE(&td
, MINT_CONV_OVF_I8_R8
);
2303 ADD_CODE(&td
, MINT_CONV_I8_I4
);
2308 g_assert_not_reached ();
2311 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
2313 #if SIZEOF_VOID_P == 8
2314 case CEE_CONV_OVF_U
:
2316 case CEE_CONV_OVF_U8
:
2317 CHECK_STACK (&td
, 1);
2318 switch (td
.sp
[-1].type
) {
2320 ADD_CODE(&td
, MINT_CONV_OVF_U8_R8
);
2323 ADD_CODE(&td
, MINT_CONV_OVF_U8_I4
);
2328 g_assert_not_reached ();
2331 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I8
);
2336 token
= read32 (td
.ip
+ 1);
2337 handle
= mono_ldtoken (image
, token
, &klass
, generic_context
);
2338 mt
= mint_type(&klass
->byval_arg
);
2339 g_assert (mt
== MINT_TYPE_VT
);
2340 size
= mono_class_value_size (klass
, NULL
);
2341 g_assert (size
== sizeof(gpointer
));
2342 PUSH_VT(&td
, sizeof(gpointer
));
2343 ADD_CODE(&td
, MINT_LDTOKEN
);
2344 ADD_CODE(&td
, get_data_item_index (&td
, handle
));
2345 PUSH_SIMPLE_TYPE(&td
, stack_type
[mt
]);
2350 binary_arith_op(&td
, MINT_ADD_OVF_I4
);
2353 case CEE_ADD_OVF_UN
:
2354 binary_arith_op(&td
, MINT_ADD_OVF_UN_I4
);
2358 binary_arith_op(&td
, MINT_MUL_OVF_I4
);
2361 case CEE_MUL_OVF_UN
:
2362 binary_arith_op(&td
, MINT_MUL_OVF_UN_I4
);
2366 binary_arith_op(&td
, MINT_SUB_OVF_I4
);
2369 case CEE_SUB_OVF_UN
:
2370 binary_arith_op(&td
, MINT_SUB_OVF_UN_I4
);
2373 case CEE_ENDFINALLY
:
2374 SIMPLE_OP (td
, MINT_ENDFINALLY
);
2375 generating_code
= 0;
2379 handle_branch (&td
, MINT_LEAVE_S
, MINT_LEAVE
, 5 + read32 (td
.ip
+ 1));
2381 generating_code
= 0;
2385 handle_branch (&td
, MINT_LEAVE_S
, MINT_LEAVE
, 2 + (gint8
)td
.ip
[1]);
2387 generating_code
= 0;
2392 case CEE_MONO_ICALL
: {
2395 MonoJitICallInfo
*info
;
2397 token
= read32 (td
.ip
+ 1);
2399 func
= mono_method_get_wrapper_data (method
, token
);
2400 info
= mono_find_jit_icall_by_addr (func
);
2403 CHECK_STACK (&td
, info
->sig
->param_count
);
2404 switch (info
->sig
->param_count
) {
2406 if (MONO_TYPE_IS_VOID (info
->sig
->ret
))
2407 ADD_CODE (&td
,MINT_ICALL_V_V
);
2409 g_assert_not_reached();
2412 if (MONO_TYPE_IS_VOID (info
->sig
->ret
))
2413 ADD_CODE (&td
,MINT_ICALL_P_V
);
2415 ADD_CODE (&td
,MINT_ICALL_P_P
);
2418 if (MONO_TYPE_IS_VOID (info
->sig
->ret
)) {
2419 if (info
->sig
->params
[1]->type
== MONO_TYPE_I4
)
2420 ADD_CODE (&td
,MINT_ICALL_PI_V
);
2422 ADD_CODE (&td
,MINT_ICALL_PP_V
);
2424 if (info
->sig
->params
[1]->type
== MONO_TYPE_I4
)
2425 ADD_CODE (&td
,MINT_ICALL_PI_P
);
2427 ADD_CODE (&td
,MINT_ICALL_PP_P
);
2431 g_assert (MONO_TYPE_IS_VOID (info
->sig
->ret
));
2432 if (info
->sig
->params
[2]->type
== MONO_TYPE_I4
)
2433 ADD_CODE (&td
,MINT_ICALL_PPI_V
);
2435 ADD_CODE (&td
,MINT_ICALL_PPP_V
);
2438 g_assert_not_reached ();
2440 g_error ("FIXME: ftnptr to delegate");
2442 if (func
== mono_ftnptr_to_delegate
)
2443 func
= mono_interp_ftnptr_to_delegate
;
2445 ADD_CODE(&td
, get_data_item_index (&td
, func
));
2446 td
.sp
-= info
->sig
->param_count
;
2448 if (!MONO_TYPE_IS_VOID (info
->sig
->ret
)) {
2450 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I
);
2454 case CEE_MONO_VTADDR
: {
2456 CHECK_STACK (&td
, 1);
2457 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
)
2458 size
= mono_class_native_size(td
.sp
[-1].klass
, NULL
);
2460 size
= mono_class_value_size(td
.sp
[-1].klass
, NULL
);
2461 size
= (size
+ 7) & ~7;
2462 ADD_CODE(&td
, MINT_VTRESULT
);
2464 WRITE32(&td
, &size
);
2467 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_MP
);
2470 case CEE_MONO_LDPTR
:
2471 case CEE_MONO_CLASSCONST
:
2472 token
= read32 (td
.ip
+ 1);
2474 ADD_CODE(&td
, MINT_MONO_LDPTR
);
2475 ADD_CODE(&td
, get_data_item_index (&td
, mono_method_get_wrapper_data (method
, token
)));
2476 td
.sp
[0].type
= STACK_TYPE_I
;
2479 case CEE_MONO_OBJADDR
:
2480 CHECK_STACK (&td
, 1);
2482 td
.sp
[-1].type
= STACK_TYPE_MP
;
2485 case CEE_MONO_NEWOBJ
:
2486 token
= read32 (td
.ip
+ 1);
2488 ADD_CODE(&td
, MINT_MONO_NEWOBJ
);
2489 ADD_CODE(&td
, get_data_item_index (&td
, mono_method_get_wrapper_data (method
, token
)));
2490 td
.sp
[0].type
= STACK_TYPE_O
;
2493 case CEE_MONO_RETOBJ
:
2494 CHECK_STACK (&td
, 1);
2495 token
= read32 (td
.ip
+ 1);
2497 ADD_CODE(&td
, MINT_MONO_RETOBJ
);
2500 klass
= (MonoClass
*)mono_method_get_wrapper_data (method
, token
);
2502 /*stackval_from_data (signature->ret, frame->retval, sp->data.vt, signature->pinvoke);*/
2504 if (td
.sp
> td
.stack
)
2505 g_warning ("CEE_MONO_RETOBJ: more values on stack: %d", td
.sp
-td
.stack
);
2507 case CEE_MONO_LDNATIVEOBJ
:
2508 token
= read32 (td
.ip
+ 1);
2510 klass
= (MonoClass
*)mono_method_get_wrapper_data (method
, token
);
2511 g_assert(klass
->valuetype
);
2512 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_MP
);
2514 case CEE_MONO_SAVE_LMF
:
2515 case CEE_MONO_RESTORE_LMF
:
2516 case CEE_MONO_NOT_TAKEN
:
2520 g_error ("transform.c: Unimplemented opcode: 0xF0 %02x at 0x%x\n", *td
.ip
, td
.ip
-header
->code
);
2530 case CEE_PREFIXREF
: ves_abort(); break;
2533 * Note: Exceptions thrown when executing a prefixed opcode need
2534 * to take into account the number of prefix bytes (usually the
2535 * throw point is just (ip - n_prefix_bytes).
2541 case CEE_ARGLIST
: ves_abort(); break;
2544 CHECK_STACK(&td
, 2);
2545 if (td
.sp
[-1].type
== STACK_TYPE_O
|| td
.sp
[-1].type
== STACK_TYPE_MP
)
2546 ADD_CODE(&td
, MINT_CEQ_I4
+ STACK_TYPE_I
- STACK_TYPE_I4
);
2548 ADD_CODE(&td
, MINT_CEQ_I4
+ td
.sp
[-1].type
- STACK_TYPE_I4
);
2550 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2554 CHECK_STACK(&td
, 2);
2555 if (td
.sp
[-1].type
== STACK_TYPE_O
|| td
.sp
[-1].type
== STACK_TYPE_MP
)
2556 ADD_CODE(&td
, MINT_CGT_I4
+ STACK_TYPE_I
- STACK_TYPE_I4
);
2558 ADD_CODE(&td
, MINT_CGT_I4
+ td
.sp
[-1].type
- STACK_TYPE_I4
);
2560 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2564 CHECK_STACK(&td
, 2);
2565 if (td
.sp
[-1].type
== STACK_TYPE_O
|| td
.sp
[-1].type
== STACK_TYPE_MP
)
2566 ADD_CODE(&td
, MINT_CGT_UN_I4
+ STACK_TYPE_I
- STACK_TYPE_I4
);
2568 ADD_CODE(&td
, MINT_CGT_UN_I4
+ td
.sp
[-1].type
- STACK_TYPE_I4
);
2570 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2574 CHECK_STACK(&td
, 2);
2575 if (td
.sp
[-1].type
== STACK_TYPE_O
|| td
.sp
[-1].type
== STACK_TYPE_MP
)
2576 ADD_CODE(&td
, MINT_CLT_I4
+ STACK_TYPE_I
- STACK_TYPE_I4
);
2578 ADD_CODE(&td
, MINT_CLT_I4
+ td
.sp
[-1].type
- STACK_TYPE_I4
);
2580 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2584 CHECK_STACK(&td
, 2);
2585 if (td
.sp
[-1].type
== STACK_TYPE_O
|| td
.sp
[-1].type
== STACK_TYPE_MP
)
2586 ADD_CODE(&td
, MINT_CLT_UN_I4
+ STACK_TYPE_I
- STACK_TYPE_I4
);
2588 ADD_CODE(&td
, MINT_CLT_UN_I4
+ td
.sp
[-1].type
- STACK_TYPE_I4
);
2590 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_I4
);
2593 case CEE_LDVIRTFTN
: /* fallthrough */
2596 if (*td
.ip
== CEE_LDVIRTFTN
) {
2597 CHECK_STACK (&td
, 1);
2600 token
= read32 (td
.ip
+ 1);
2601 if (method
->wrapper_type
!= MONO_WRAPPER_NONE
)
2602 m
= (MonoMethod
*)mono_method_get_wrapper_data (method
, token
);
2604 m
= mono_get_method_full (image
, token
, NULL
, generic_context
);
2606 if (method
->wrapper_type
== MONO_WRAPPER_NONE
&& m
->iflags
& METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED
)
2607 m
= mono_marshal_get_synchronized_wrapper (m
);
2609 ADD_CODE(&td
, *td
.ip
== CEE_LDFTN
? MINT_LDFTN
: MINT_LDVIRTFTN
);
2610 ADD_CODE(&td
, get_data_item_index (&td
, mono_interp_get_runtime_method (domain
, m
, &error
)));
2611 mono_error_cleanup (&error
); /* FIXME: don't swallow the error */
2613 PUSH_SIMPLE_TYPE (&td
, STACK_TYPE_F
);
2617 load_arg (&td
, read16 (td
.ip
+ 1));
2621 int n
= read16 (td
.ip
+ 1);
2622 if (n
== 0 && signature
->hasthis
)
2623 ADD_CODE(&td
, MINT_LDTHISA
);
2625 ADD_CODE(&td
, MINT_LDARGA
);
2626 ADD_CODE(&td
, td
.rtm
->arg_offsets
[n
- signature
->hasthis
]); /* FIX for large offsets */
2628 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_MP
);
2633 store_arg (&td
, read16 (td
.ip
+ 1));
2637 load_local (&td
, read16 (td
.ip
+ 1));
2641 ADD_CODE(&td
, MINT_LDLOCA_S
);
2642 ADD_CODE(&td
, td
.rtm
->local_offsets
[read16 (td
.ip
+ 1)]);
2643 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_MP
);
2647 store_local (&td
, read16 (td
.ip
+ 1));
2651 CHECK_STACK (&td
, 1);
2652 #if SIZEOF_VOID_P == 8
2653 if (td
.sp
[-1].type
== STACK_TYPE_I8
)
2654 ADD_CODE(&td
, MINT_CONV_I4_I8
);
2656 ADD_CODE(&td
, MINT_LOCALLOC
);
2657 if (td
.sp
!= td
.stack
+ 1)
2658 g_warning("CEE_LOCALLOC: stack not empty");
2660 SET_SIMPLE_TYPE(td
.sp
- 1, STACK_TYPE_MP
);
2663 case CEE_UNUSED57
: ves_abort(); break;
2664 case CEE_ENDFILTER
: ves_abort(); break;
2666 case CEE_UNALIGNED_
:
2668 /* FIX: should do something? */;
2672 /* FIX: should do something? */;
2676 /* FIX: should do something? */;
2679 CHECK_STACK(&td
, 1);
2680 token
= read32 (td
.ip
+ 1);
2681 klass
= mono_class_get_full (image
, token
, generic_context
);
2682 ADD_CODE(&td
, MINT_INITOBJ
);
2683 i32
= mono_class_value_size (klass
, NULL
);
2689 CHECK_STACK(&td
, 3);
2690 /* FIX? convert length to I8? */
2691 ADD_CODE(&td
, MINT_CPBLK
);
2696 case CEE_CONSTRAINED_
: {
2698 /* FIXME: implement */
2700 token
= read32 (ip
);
2706 CHECK_STACK(&td
, 3);
2707 ADD_CODE(&td
, MINT_INITBLK
);
2712 /* FIXME: implement */
2717 SIMPLE_OP (td
, MINT_RETHROW
);
2718 generating_code
= 0;
2723 token
= read32 (td
.ip
+ 1);
2725 if (mono_metadata_token_table (token
) == MONO_TABLE_TYPESPEC
) {
2726 MonoType
*type
= mono_type_create_from_typespec (image
, token
);
2727 size
= mono_type_size (type
, &align
);
2729 MonoClass
*szclass
= mono_class_get_full (image
, token
, generic_context
);
2730 mono_class_init (szclass
);
2732 if (!szclass
->valuetype
)
2733 THROW_EX (mono_exception_from_name (mono_defaults
.corlib
, "System", "InvalidProgramException"), ip
- 5);
2735 size
= mono_class_value_size (szclass
, &align
);
2737 ADD_CODE(&td
, MINT_LDC_I4
);
2738 WRITE32(&td
, &size
);
2739 PUSH_SIMPLE_TYPE(&td
, STACK_TYPE_I4
);
2743 case CEE_REFANYTYPE
: ves_abort(); break;
2746 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
);
2750 g_error ("transform.c: Unimplemented opcode: %02x at 0x%x\n", *td
.ip
, td
.ip
-header
->code
);
2753 if (td
.new_ip
- td
.new_code
!= new_in_start_offset
)
2754 td
.last_new_ip
= td
.new_code
+ new_in_start_offset
;
2755 else if (td
.is_bb_start
[td
.in_start
- td
.il_code
])
2756 td
.is_bb_start
[td
.ip
- td
.il_code
] = 1;
2758 td
.last_ip
= td
.in_start
;
2761 if (mono_interp_traceopt
) {
2762 const guint16
*p
= td
.new_code
;
2763 printf("Runtime method: %p, VT stack size: %d\n", rtm
, td
.max_vt_sp
);
2764 printf("Calculated stack size: %d, stated size: %d\n", td
.max_stack_height
, header
->max_stack
);
2765 while (p
< td
.new_ip
) {
2766 p
= mono_interp_dis_mintop(td
.new_code
, p
);
2771 rtm
->clauses
= mono_mempool_alloc (domain
->mp
, header
->num_clauses
* sizeof(MonoExceptionClause
));
2772 memcpy (rtm
->clauses
, header
->clauses
, header
->num_clauses
* sizeof(MonoExceptionClause
));
2773 rtm
->code
= mono_mempool_alloc (domain
->mp
, (td
.new_ip
- td
.new_code
) * sizeof(gushort
));
2774 memcpy (rtm
->code
, td
.new_code
, (td
.new_ip
- td
.new_code
) * sizeof(gushort
));
2775 g_free (td
.new_code
);
2776 rtm
->new_body_start
= rtm
->code
+ body_start_offset
;
2777 rtm
->num_clauses
= header
->num_clauses
;
2778 for (i
= 0; i
< header
->num_clauses
; i
++) {
2779 MonoExceptionClause
*c
= rtm
->clauses
+ i
;
2780 int end_off
= c
->try_offset
+ c
->try_len
;
2781 c
->try_offset
= td
.in_offsets
[c
->try_offset
];
2782 c
->try_len
= td
.in_offsets
[end_off
] - c
->try_offset
;
2783 end_off
= c
->handler_offset
+ c
->handler_len
;
2784 c
->handler_offset
= td
.in_offsets
[c
->handler_offset
];
2785 c
->handler_len
= td
.in_offsets
[end_off
] - c
->handler_offset
;
2787 rtm
->vt_stack_size
= td
.max_vt_sp
;
2788 rtm
->alloca_size
= rtm
->locals_size
+ rtm
->args_size
+ rtm
->vt_stack_size
+ rtm
->stack_size
;
2789 rtm
->data_items
= mono_mempool_alloc (domain
->mp
, td
.n_data_items
* sizeof (td
.data_items
[0]));
2790 memcpy (rtm
->data_items
, td
.data_items
, td
.n_data_items
* sizeof (td
.data_items
[0]));
2791 g_free (td
.in_offsets
);
2792 g_free (td
.forward_refs
);
2793 for (i
= 0; i
< header
->code_size
; ++i
)
2794 g_free (td
.stack_state
[i
]);
2795 g_free (td
.stack_state
);
2796 g_free (td
.stack_height
);
2797 g_free (td
.vt_stack_size
);
2798 g_free (td
.data_items
);
2799 g_hash_table_destroy (td
.data_hash
);
2802 static mono_mutex_t calc_section
;
2805 mono_interp_transform_init (void)
2807 mono_os_mutex_init_recursive(&calc_section
);
2811 mono_interp_transform_method (RuntimeMethod
*runtime_method
, ThreadContext
*context
)
2813 int i
, align
, size
, offset
;
2814 MonoMethod
*method
= runtime_method
->method
;
2815 MonoImage
*image
= method
->klass
->image
;
2816 MonoMethodHeader
*header
= mono_method_get_header (method
);
2817 MonoMethodSignature
*signature
= mono_method_signature (method
);
2818 register const unsigned char *ip
, *end
;
2819 const MonoOpcode
*opcode
;
2822 MonoDomain
*domain
= mono_domain_get ();
2823 unsigned char *is_bb_start
;
2825 MonoVTable
*method_class_vt
;
2827 MonoGenericContext
*generic_context
= NULL
;
2829 // g_printerr ("TRANSFORM(0x%016lx): begin %s::%s\n", mono_thread_current (), method->klass->name, method->name);
2830 method_class_vt
= mono_class_vtable (domain
, runtime_method
->method
->klass
);
2831 if (!method_class_vt
->initialized
) {
2833 MonoInvocation
*last_env_frame
= context
->env_frame
;
2834 jmp_buf *old_env
= context
->current_env
;
2837 MonoException
*failed
= context
->env_frame
->ex
;
2838 context
->env_frame
->ex
= NULL
;
2839 context
->env_frame
= last_env_frame
;
2840 context
->current_env
= old_env
;
2843 context
->env_frame
= context
->current_frame
;
2844 context
->current_env
= &env
;
2845 mono_runtime_class_init (method_class_vt
);
2846 context
->env_frame
= last_env_frame
;
2847 context
->current_env
= old_env
;
2850 mono_profiler_method_jit (method
); /* sort of... */
2852 if (mono_method_signature (method
)->is_inflated
)
2853 generic_context
= &((MonoMethodInflated
*) method
)->context
;
2855 if (method
->iflags
& (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
| METHOD_IMPL_ATTRIBUTE_RUNTIME
)) {
2856 MonoMethod
*nm
= NULL
;
2857 mono_os_mutex_lock(&calc_section
);
2858 if (runtime_method
->transformed
) {
2859 mono_os_mutex_unlock(&calc_section
);
2860 g_error ("FIXME: no jit info?");
2861 mono_profiler_method_end_jit (method
, NULL
, MONO_PROFILE_OK
);
2865 /* assumes all internal calls with an array this are built in... */
2866 if (method
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
&& (! mono_method_signature (method
)->hasthis
|| method
->klass
->rank
== 0)) {
2867 runtime_method
->code
= g_malloc (sizeof (short));
2868 runtime_method
->code
[0] = MINT_CALLINT
;
2869 g_assert (((MonoMethodPInvoke
*) method
)->addr
== NULL
);
2870 if (((MonoMethodPInvoke
*) method
)->addr
== NULL
)
2871 ((MonoMethodPInvoke
*) method
)->addr
= mono_lookup_internal_call (method
);
2873 g_error ("FIXME: arch_trampoline, not available?");
2874 runtime_method
->func
= mono_arch_create_trampoline (mono_method_signature (method
), method
->string_ctor
);
2877 const char *name
= method
->name
;
2878 if (method
->klass
->parent
== mono_defaults
.multicastdelegate_class
) {
2879 if (*name
== 'I' && (strcmp (name
, "Invoke") == 0)) {
2880 g_error ("FIXME: no del?");
2881 nm
= mono_marshal_get_delegate_invoke (method
, NULL
);
2882 } else if (*name
== 'B' && (strcmp (name
, "BeginInvoke") == 0)) {
2883 nm
= mono_marshal_get_delegate_begin_invoke (method
);
2884 } else if (*name
== 'E' && (strcmp (name
, "EndInvoke") == 0)) {
2885 nm
= mono_marshal_get_delegate_end_invoke (method
);
2889 runtime_method
->code
= g_malloc(sizeof(short));
2890 runtime_method
->code
[0] = MINT_CALLRUN
;
2894 runtime_method
->stack_size
= sizeof (stackval
); /* for tracing */
2895 runtime_method
->alloca_size
= runtime_method
->stack_size
;
2896 runtime_method
->transformed
= TRUE
;
2897 mono_os_mutex_unlock(&calc_section
);
2898 mono_profiler_method_end_jit (method
, NULL
, MONO_PROFILE_OK
);
2902 header
= mono_method_get_header (nm
);
2903 mono_os_mutex_unlock(&calc_section
);
2905 g_assert ((signature
->param_count
+ signature
->hasthis
) < 1000);
2906 g_assert (header
->max_stack
< 10000);
2907 /* intern the strings in the method. */
2909 end
= ip
+ header
->code_size
;
2911 is_bb_start
= g_malloc0(header
->code_size
);
2912 is_bb_start
[0] = 1;
2919 else if (in
== 0xf0) {
2921 in
= *ip
+ MONO_CEE_MONO_ICALL
;
2923 opcode
= &mono_opcodes
[in
];
2924 switch (opcode
->argument
) {
2925 case MonoInlineNone
:
2928 case MonoInlineString
:
2929 if (method
->wrapper_type
== MONO_WRAPPER_NONE
)
2930 mono_ldstr (domain
, image
, mono_metadata_token_index (read32 (ip
+ 1)));
2933 case MonoInlineType
:
2934 if (method
->wrapper_type
== MONO_WRAPPER_NONE
) {
2935 class = mono_class_get_full (image
, read32 (ip
+ 1), generic_context
);
2936 mono_class_init (class);
2937 /* quick fix to not do this for the fake ptr classes - probably should not be getting the vtable at all here */
2939 g_error ("FIXME: interface method lookup: %s (in method %s)", class->name
, method
->name
);
2940 if (!(class->flags
& TYPE_ATTRIBUTE_INTERFACE
) && class->interface_offsets
!= NULL
)
2941 mono_class_vtable (domain
, class);
2946 case MonoInlineMethod
:
2947 if (method
->wrapper_type
== MONO_WRAPPER_NONE
&& *ip
!= CEE_CALLI
) {
2948 m
= mono_get_method_full (image
, read32 (ip
+ 1), NULL
, generic_context
);
2950 g_free (is_bb_start
);
2951 g_error ("FIXME: where to get method and class string?");
2953 // return mono_get_exception_missing_method ();
2955 mono_class_init (m
->klass
);
2956 if (!(m
->klass
->flags
& TYPE_ATTRIBUTE_INTERFACE
))
2957 mono_class_vtable (domain
, m
->klass
);
2961 case MonoInlineField
:
2965 case MonoShortInlineR
:
2968 case MonoInlineBrTarget
:
2969 offset
= read32 (ip
+ 1);
2971 backwards
= offset
< 0;
2972 offset
+= ip
- header
->code
;
2973 g_assert (offset
>= 0 && offset
< header
->code_size
);
2974 is_bb_start
[offset
] |= backwards
? 2 : 1;
2976 case MonoShortInlineBrTarget
:
2977 offset
= ((gint8
*)ip
) [1];
2979 backwards
= offset
< 0;
2980 offset
+= ip
- header
->code
;
2981 g_assert (offset
>= 0 && offset
< header
->code_size
);
2982 is_bb_start
[offset
] |= backwards
? 2 : 1;
2987 case MonoShortInlineVar
:
2988 case MonoShortInlineI
:
2991 case MonoInlineSwitch
: {
2993 const unsigned char *next_ip
;
2997 next_ip
= ip
+ 4 * n
;
2998 for (i
= 0; i
< n
; i
++) {
2999 offset
= read32 (ip
);
3000 backwards
= offset
< 0;
3001 offset
+= next_ip
- header
->code
;
3002 g_assert (offset
>= 0 && offset
< header
->code_size
);
3003 is_bb_start
[offset
] |= backwards
? 2 : 1;
3013 g_assert_not_reached ();
3016 // g_printerr ("TRANSFORM(0x%016lx): end %s::%s\n", mono_thread_current (), method->klass->name, method->name);
3018 /* the rest needs to be locked so it is only done once */
3019 mono_os_mutex_lock(&calc_section
);
3020 if (runtime_method
->transformed
) {
3021 mono_os_mutex_unlock(&calc_section
);
3022 g_free (is_bb_start
);
3023 mono_profiler_method_end_jit (method
, NULL
, MONO_PROFILE_OK
);
3027 runtime_method
->local_offsets
= g_malloc (header
->num_locals
* sizeof(guint32
));
3028 runtime_method
->stack_size
= (sizeof (stackval
) + 2) * header
->max_stack
; /* + 1 for returns of called functions + 1 for 0-ing in trace*/
3029 runtime_method
->stack_size
= (runtime_method
->stack_size
+ 7) & ~7;
3031 for (i
= 0; i
< header
->num_locals
; ++i
) {
3032 size
= mono_type_size (header
->locals
[i
], &align
);
3033 offset
+= align
- 1;
3034 offset
&= ~(align
- 1);
3035 runtime_method
->local_offsets
[i
] = offset
;
3038 offset
= (offset
+ 7) & ~7;
3039 runtime_method
->locals_size
= offset
;
3040 g_assert (runtime_method
->locals_size
< 65536);
3042 runtime_method
->arg_offsets
= g_malloc(signature
->param_count
* sizeof(guint32
));
3043 for (i
= 0; i
< signature
->param_count
; ++i
) {
3044 if (signature
->pinvoke
) {
3045 size
= mono_type_native_stack_size (signature
->params
[i
], &align
);
3049 size
= mono_type_stack_size (signature
->params
[i
], &align
);
3050 offset
+= align
- 1;
3051 offset
&= ~(align
- 1);
3052 runtime_method
->arg_offsets
[i
] = offset
;
3055 offset
= (offset
+ 7) & ~7;
3056 runtime_method
->args_size
= offset
;
3057 g_assert (runtime_method
->args_size
< 10000);
3059 generate(method
, runtime_method
, is_bb_start
);
3061 g_free (is_bb_start
);
3063 mono_profiler_method_end_jit (method
, NULL
, MONO_PROFILE_OK
);
3064 runtime_method
->transformed
= TRUE
;
3065 mono_os_mutex_unlock(&calc_section
);