Merge pull request #2154 from BrennanConroy/bug_30018
[mono.git] / mono / mini / method-to-ir.c
1 /*
2  * method-to-ir.c: Convert CIL to the JIT internal representation
3  *
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *   Dietmar Maurer (dietmar@ximian.com)
7  *
8  * (C) 2002 Ximian, Inc.
9  * Copyright 2003-2010 Novell, Inc (http://www.novell.com)
10  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
11  */
12
13 #include <config.h>
14
15 #ifndef DISABLE_JIT
16
17 #include <signal.h>
18
19 #ifdef HAVE_UNISTD_H
20 #include <unistd.h>
21 #endif
22
23 #include <math.h>
24 #include <string.h>
25 #include <ctype.h>
26
27 #ifdef HAVE_SYS_TIME_H
28 #include <sys/time.h>
29 #endif
30
31 #ifdef HAVE_ALLOCA_H
32 #include <alloca.h>
33 #endif
34
35 #include <mono/utils/memcheck.h>
36 #include "mini.h"
37 #include <mono/metadata/abi-details.h>
38 #include <mono/metadata/assembly.h>
39 #include <mono/metadata/attrdefs.h>
40 #include <mono/metadata/loader.h>
41 #include <mono/metadata/tabledefs.h>
42 #include <mono/metadata/class.h>
43 #include <mono/metadata/object.h>
44 #include <mono/metadata/exception.h>
45 #include <mono/metadata/opcodes.h>
46 #include <mono/metadata/mono-endian.h>
47 #include <mono/metadata/tokentype.h>
48 #include <mono/metadata/tabledefs.h>
49 #include <mono/metadata/marshal.h>
50 #include <mono/metadata/debug-helpers.h>
51 #include <mono/metadata/mono-debug.h>
52 #include <mono/metadata/mono-debug-debugger.h>
53 #include <mono/metadata/gc-internal.h>
54 #include <mono/metadata/security-manager.h>
55 #include <mono/metadata/threads-types.h>
56 #include <mono/metadata/security-core-clr.h>
57 #include <mono/metadata/profiler-private.h>
58 #include <mono/metadata/profiler.h>
59 #include <mono/metadata/debug-mono-symfile.h>
60 #include <mono/utils/mono-compiler.h>
61 #include <mono/utils/mono-memory-model.h>
62 #include <mono/metadata/mono-basic-block.h>
63
64 #include "trace.h"
65
66 #include "ir-emit.h"
67
68 #include "jit-icalls.h"
69 #include "jit.h"
70 #include "debugger-agent.h"
71 #include "seq-points.h"
72
73 #define BRANCH_COST 10
74 #define INLINE_LENGTH_LIMIT 20
75
76 /* These have 'cfg' as an implicit argument */
77 #define INLINE_FAILURE(msg) do {                                                                        \
78         if ((cfg->method != cfg->current_method) && (cfg->current_method->wrapper_type == MONO_WRAPPER_NONE)) { \
79                 inline_failure (cfg, msg);                                                                              \
80                 goto exception_exit;                                                                                    \
81         } \
82         } while (0)
83 #define CHECK_CFG_EXCEPTION do {\
84                 if (cfg->exception_type != MONO_EXCEPTION_NONE) \
85                         goto exception_exit;                                            \
86         } while (0)
87 #define METHOD_ACCESS_FAILURE(method, cmethod) do {                     \
88                 method_access_failure ((cfg), (method), (cmethod));                     \
89                 goto exception_exit;                                                                            \
90         } while (0)
91 #define FIELD_ACCESS_FAILURE(method, field) do {                                        \
92                 field_access_failure ((cfg), (method), (field));                        \
93                 goto exception_exit;    \
94         } while (0)
95 #define GENERIC_SHARING_FAILURE(opcode) do {            \
96                 if (cfg->gshared) {                                                                     \
97                         gshared_failure (cfg, opcode, __FILE__, __LINE__);      \
98                         goto exception_exit;    \
99                 }                       \
100         } while (0)
101 #define GSHAREDVT_FAILURE(opcode) do {          \
102         if (cfg->gsharedvt) {                                                                                           \
103                 gsharedvt_failure (cfg, opcode, __FILE__, __LINE__);                    \
104                 goto exception_exit;                                                                                    \
105         }                                                                                                                                       \
106         } while (0)
107 #define OUT_OF_MEMORY_FAILURE do {      \
108                 mono_cfg_set_exception (cfg, MONO_EXCEPTION_OUT_OF_MEMORY);             \
109                 goto exception_exit;    \
110         } while (0)
111 #define DISABLE_AOT(cfg) do { \
112                 if ((cfg)->verbose_level >= 2)                                            \
113                         printf ("AOT disabled: %s:%d\n", __FILE__, __LINE__);   \
114                 (cfg)->disable_aot = TRUE;                                                        \
115         } while (0)
116 #define LOAD_ERROR do { \
117                 break_on_unverified ();                                                         \
118                 mono_cfg_set_exception (cfg, MONO_EXCEPTION_TYPE_LOAD); \
119                 goto exception_exit;                                                                    \
120         } while (0)
121
122 #define TYPE_LOAD_ERROR(klass) do { \
123                 cfg->exception_ptr = klass; \
124                 LOAD_ERROR;                                     \
125         } while (0)
126
127 #define CHECK_CFG_ERROR do {\
128                 if (!mono_error_ok (&cfg->error)) { \
129                         mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);        \
130                         goto mono_error_exit; \
131                 } \
132         } while (0)
133
134 /* Determine whenever 'ins' represents a load of the 'this' argument */
135 #define MONO_CHECK_THIS(ins) (mono_method_signature (cfg->method)->hasthis && ((ins)->opcode == OP_MOVE) && ((ins)->sreg1 == cfg->args [0]->dreg))
136
137 static int ldind_to_load_membase (int opcode);
138 static int stind_to_store_membase (int opcode);
139
140 int mono_op_to_op_imm (int opcode);
141 int mono_op_to_op_imm_noemul (int opcode);
142
143 MONO_API MonoInst* mono_emit_native_call (MonoCompile *cfg, gconstpointer func, MonoMethodSignature *sig, MonoInst **args);
144
145 static int inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **sp,
146                                                   guchar *ip, guint real_offset, gboolean inline_always);
147
148 /* helper methods signatures */
149 static MonoMethodSignature *helper_sig_domain_get;
150 static MonoMethodSignature *helper_sig_rgctx_lazy_fetch_trampoline;
151
152 /*
153  * Instruction metadata
154  */
155 #ifdef MINI_OP
156 #undef MINI_OP
157 #endif
158 #ifdef MINI_OP3
159 #undef MINI_OP3
160 #endif
161 #define MINI_OP(a,b,dest,src1,src2) dest, src1, src2, ' ',
162 #define MINI_OP3(a,b,dest,src1,src2,src3) dest, src1, src2, src3,
163 #define NONE ' '
164 #define IREG 'i'
165 #define FREG 'f'
166 #define VREG 'v'
167 #define XREG 'x'
168 #if SIZEOF_REGISTER == 8 && SIZEOF_REGISTER == SIZEOF_VOID_P
169 #define LREG IREG
170 #else
171 #define LREG 'l'
172 #endif
173 /* keep in sync with the enum in mini.h */
174 const char
175 ins_info[] = {
176 #include "mini-ops.h"
177 };
178 #undef MINI_OP
179 #undef MINI_OP3
180
181 #define MINI_OP(a,b,dest,src1,src2) ((src2) != NONE ? 2 : ((src1) != NONE ? 1 : 0)),
182 #define MINI_OP3(a,b,dest,src1,src2,src3) ((src3) != NONE ? 3 : ((src2) != NONE ? 2 : ((src1) != NONE ? 1 : 0))),
183 /* 
184  * This should contain the index of the last sreg + 1. This is not the same
185  * as the number of sregs for opcodes like IA64_CMP_EQ_IMM.
186  */
187 const gint8 ins_sreg_counts[] = {
188 #include "mini-ops.h"
189 };
190 #undef MINI_OP
191 #undef MINI_OP3
192
193 #define MONO_INIT_VARINFO(vi,id) do { \
194         (vi)->range.first_use.pos.bid = 0xffff; \
195         (vi)->reg = -1; \
196         (vi)->idx = (id); \
197 } while (0)
198
199 guint32
200 mono_alloc_ireg (MonoCompile *cfg)
201 {
202         return alloc_ireg (cfg);
203 }
204
205 guint32
206 mono_alloc_lreg (MonoCompile *cfg)
207 {
208         return alloc_lreg (cfg);
209 }
210
211 guint32
212 mono_alloc_freg (MonoCompile *cfg)
213 {
214         return alloc_freg (cfg);
215 }
216
217 guint32
218 mono_alloc_preg (MonoCompile *cfg)
219 {
220         return alloc_preg (cfg);
221 }
222
223 guint32
224 mono_alloc_dreg (MonoCompile *cfg, MonoStackType stack_type)
225 {
226         return alloc_dreg (cfg, stack_type);
227 }
228
229 /*
230  * mono_alloc_ireg_ref:
231  *
232  *   Allocate an IREG, and mark it as holding a GC ref.
233  */
234 guint32
235 mono_alloc_ireg_ref (MonoCompile *cfg)
236 {
237         return alloc_ireg_ref (cfg);
238 }
239
240 /*
241  * mono_alloc_ireg_mp:
242  *
243  *   Allocate an IREG, and mark it as holding a managed pointer.
244  */
245 guint32
246 mono_alloc_ireg_mp (MonoCompile *cfg)
247 {
248         return alloc_ireg_mp (cfg);
249 }
250
251 /*
252  * mono_alloc_ireg_copy:
253  *
254  *   Allocate an IREG with the same GC type as VREG.
255  */
256 guint32
257 mono_alloc_ireg_copy (MonoCompile *cfg, guint32 vreg)
258 {
259         if (vreg_is_ref (cfg, vreg))
260                 return alloc_ireg_ref (cfg);
261         else if (vreg_is_mp (cfg, vreg))
262                 return alloc_ireg_mp (cfg);
263         else
264                 return alloc_ireg (cfg);
265 }
266
267 guint
268 mono_type_to_regmove (MonoCompile *cfg, MonoType *type)
269 {
270         if (type->byref)
271                 return OP_MOVE;
272
273         type = mini_get_underlying_type (type);
274 handle_enum:
275         switch (type->type) {
276         case MONO_TYPE_I1:
277         case MONO_TYPE_U1:
278                 return OP_MOVE;
279         case MONO_TYPE_I2:
280         case MONO_TYPE_U2:
281                 return OP_MOVE;
282         case MONO_TYPE_I4:
283         case MONO_TYPE_U4:
284                 return OP_MOVE;
285         case MONO_TYPE_I:
286         case MONO_TYPE_U:
287         case MONO_TYPE_PTR:
288         case MONO_TYPE_FNPTR:
289                 return OP_MOVE;
290         case MONO_TYPE_CLASS:
291         case MONO_TYPE_STRING:
292         case MONO_TYPE_OBJECT:
293         case MONO_TYPE_SZARRAY:
294         case MONO_TYPE_ARRAY:    
295                 return OP_MOVE;
296         case MONO_TYPE_I8:
297         case MONO_TYPE_U8:
298 #if SIZEOF_REGISTER == 8
299                 return OP_MOVE;
300 #else
301                 return OP_LMOVE;
302 #endif
303         case MONO_TYPE_R4:
304                 return cfg->r4fp ? OP_RMOVE : OP_FMOVE;
305         case MONO_TYPE_R8:
306                 return OP_FMOVE;
307         case MONO_TYPE_VALUETYPE:
308                 if (type->data.klass->enumtype) {
309                         type = mono_class_enum_basetype (type->data.klass);
310                         goto handle_enum;
311                 }
312                 if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type (type)))
313                         return OP_XMOVE;
314                 return OP_VMOVE;
315         case MONO_TYPE_TYPEDBYREF:
316                 return OP_VMOVE;
317         case MONO_TYPE_GENERICINST:
318                 type = &type->data.generic_class->container_class->byval_arg;
319                 goto handle_enum;
320         case MONO_TYPE_VAR:
321         case MONO_TYPE_MVAR:
322                 g_assert (cfg->gshared);
323                 if (mini_type_var_is_vt (type))
324                         return OP_VMOVE;
325                 else
326                         return mono_type_to_regmove (cfg, mini_get_underlying_type (type));
327         default:
328                 g_error ("unknown type 0x%02x in type_to_regstore", type->type);
329         }
330         return -1;
331 }
332
333 void
334 mono_print_bb (MonoBasicBlock *bb, const char *msg)
335 {
336         int i;
337         MonoInst *tree;
338
339         printf ("\n%s %d: [IN: ", msg, bb->block_num);
340         for (i = 0; i < bb->in_count; ++i)
341                 printf (" BB%d(%d)", bb->in_bb [i]->block_num, bb->in_bb [i]->dfn);
342         printf (", OUT: ");
343         for (i = 0; i < bb->out_count; ++i)
344                 printf (" BB%d(%d)", bb->out_bb [i]->block_num, bb->out_bb [i]->dfn);
345         printf (" ]\n");
346         for (tree = bb->code; tree; tree = tree->next)
347                 mono_print_ins_index (-1, tree);
348 }
349
350 void
351 mono_create_helper_signatures (void)
352 {
353         helper_sig_domain_get = mono_create_icall_signature ("ptr");
354         helper_sig_rgctx_lazy_fetch_trampoline = mono_create_icall_signature ("ptr ptr");
355 }
356
357 static MONO_NEVER_INLINE void
358 break_on_unverified (void)
359 {
360         if (mini_get_debug_options ()->break_on_unverified)
361                 G_BREAKPOINT ();
362 }
363
364 static MONO_NEVER_INLINE void
365 method_access_failure (MonoCompile *cfg, MonoMethod *method, MonoMethod *cil_method)
366 {
367         char *method_fname = mono_method_full_name (method, TRUE);
368         char *cil_method_fname = mono_method_full_name (cil_method, TRUE);
369         mono_cfg_set_exception (cfg, MONO_EXCEPTION_METHOD_ACCESS);
370         cfg->exception_message = g_strdup_printf ("Method `%s' is inaccessible from method `%s'\n", cil_method_fname, method_fname);
371         g_free (method_fname);
372         g_free (cil_method_fname);
373 }
374
375 static MONO_NEVER_INLINE void
376 field_access_failure (MonoCompile *cfg, MonoMethod *method, MonoClassField *field)
377 {
378         char *method_fname = mono_method_full_name (method, TRUE);
379         char *field_fname = mono_field_full_name (field);
380         mono_cfg_set_exception (cfg, MONO_EXCEPTION_FIELD_ACCESS);
381         cfg->exception_message = g_strdup_printf ("Field `%s' is inaccessible from method `%s'\n", field_fname, method_fname);
382         g_free (method_fname);
383         g_free (field_fname);
384 }
385
386 static MONO_NEVER_INLINE void
387 inline_failure (MonoCompile *cfg, const char *msg)
388 {
389         if (cfg->verbose_level >= 2)
390                 printf ("inline failed: %s\n", msg);
391         mono_cfg_set_exception (cfg, MONO_EXCEPTION_INLINE_FAILED);
392 }
393
394 static MONO_NEVER_INLINE void
395 gshared_failure (MonoCompile *cfg, int opcode, const char *file, int line)
396 {
397         if (cfg->verbose_level > 2)                                                                                     \
398                 printf ("sharing failed for method %s.%s.%s/%d opcode %s line %d\n", cfg->current_method->klass->name_space, cfg->current_method->klass->name, cfg->current_method->name, cfg->current_method->signature->param_count, mono_opcode_name ((opcode)), line);
399         mono_cfg_set_exception (cfg, MONO_EXCEPTION_GENERIC_SHARING_FAILED);
400 }
401
402 static MONO_NEVER_INLINE void
403 gsharedvt_failure (MonoCompile *cfg, int opcode, const char *file, int line)
404 {
405         cfg->exception_message = g_strdup_printf ("gsharedvt failed for method %s.%s.%s/%d opcode %s %s:%d", cfg->current_method->klass->name_space, cfg->current_method->klass->name, cfg->current_method->name, cfg->current_method->signature->param_count, mono_opcode_name ((opcode)), file, line);
406         if (cfg->verbose_level >= 2)
407                 printf ("%s\n", cfg->exception_message);
408         mono_cfg_set_exception (cfg, MONO_EXCEPTION_GENERIC_SHARING_FAILED);
409 }
410
411 /*
412  * When using gsharedvt, some instatiations might be verifiable, and some might be not. i.e. 
413  * foo<T> (int i) { ldarg.0; box T; }
414  */
415 #define UNVERIFIED do { \
416         if (cfg->gsharedvt) { \
417                 if (cfg->verbose_level > 2)                                                                     \
418                         printf ("gsharedvt method failed to verify, falling back to instantiation.\n"); \
419                 mono_cfg_set_exception (cfg, MONO_EXCEPTION_GENERIC_SHARING_FAILED); \
420                 goto exception_exit;                                                                                    \
421         }                                                                                                                                       \
422         break_on_unverified ();                                                                                         \
423         goto unverified;                                                                                                        \
424 } while (0)
425
426 #define GET_BBLOCK(cfg,tblock,ip) do {  \
427                 (tblock) = cfg->cil_offset_to_bb [(ip) - cfg->cil_start]; \
428                 if (!(tblock)) {        \
429                         if ((ip) >= end || (ip) < header->code) UNVERIFIED; \
430             NEW_BBLOCK (cfg, (tblock)); \
431                         (tblock)->cil_code = (ip);      \
432                         ADD_BBLOCK (cfg, (tblock));     \
433                 } \
434         } while (0)
435
436 #if defined(TARGET_X86) || defined(TARGET_AMD64)
437 #define EMIT_NEW_X86_LEA(cfg,dest,sr1,sr2,shift,imm) do { \
438                 MONO_INST_NEW (cfg, dest, OP_X86_LEA); \
439                 (dest)->dreg = alloc_ireg_mp ((cfg)); \
440                 (dest)->sreg1 = (sr1); \
441                 (dest)->sreg2 = (sr2); \
442                 (dest)->inst_imm = (imm); \
443                 (dest)->backend.shift_amount = (shift); \
444                 MONO_ADD_INS ((cfg)->cbb, (dest)); \
445         } while (0)
446 #endif
447
448 /* Emit conversions so both operands of a binary opcode are of the same type */
449 static void
450 add_widen_op (MonoCompile *cfg, MonoInst *ins, MonoInst **arg1_ref, MonoInst **arg2_ref)
451 {
452         MonoInst *arg1 = *arg1_ref;
453         MonoInst *arg2 = *arg2_ref;
454
455         if (cfg->r4fp &&
456                 ((arg1->type == STACK_R4 && arg2->type == STACK_R8) ||
457                  (arg1->type == STACK_R8 && arg2->type == STACK_R4))) {
458                 MonoInst *conv;
459
460                 /* Mixing r4/r8 is allowed by the spec */
461                 if (arg1->type == STACK_R4) {
462                         int dreg = alloc_freg (cfg);
463
464                         EMIT_NEW_UNALU (cfg, conv, OP_RCONV_TO_R8, dreg, arg1->dreg);
465                         conv->type = STACK_R8;
466                         ins->sreg1 = dreg;
467                         *arg1_ref = conv;
468                 }
469                 if (arg2->type == STACK_R4) {
470                         int dreg = alloc_freg (cfg);
471
472                         EMIT_NEW_UNALU (cfg, conv, OP_RCONV_TO_R8, dreg, arg2->dreg);
473                         conv->type = STACK_R8;
474                         ins->sreg2 = dreg;
475                         *arg2_ref = conv;
476                 }
477         }
478
479 #if SIZEOF_REGISTER == 8
480         /* FIXME: Need to add many more cases */
481         if ((arg1)->type == STACK_PTR && (arg2)->type == STACK_I4) {
482                 MonoInst *widen;
483
484                 int dr = alloc_preg (cfg);
485                 EMIT_NEW_UNALU (cfg, widen, OP_SEXT_I4, dr, (arg2)->dreg);
486                 (ins)->sreg2 = widen->dreg;
487         }
488 #endif
489 }
490
491 #define ADD_BINOP(op) do {      \
492                 MONO_INST_NEW (cfg, ins, (op)); \
493                 sp -= 2;        \
494                 ins->sreg1 = sp [0]->dreg;      \
495                 ins->sreg2 = sp [1]->dreg;      \
496                 type_from_op (cfg, ins, sp [0], sp [1]);        \
497                 CHECK_TYPE (ins);       \
498                 /* Have to insert a widening op */               \
499         add_widen_op (cfg, ins, &sp [0], &sp [1]);               \
500         ins->dreg = alloc_dreg ((cfg), (ins)->type); \
501         MONO_ADD_INS ((cfg)->cbb, (ins)); \
502         *sp++ = mono_decompose_opcode ((cfg), (ins));   \
503         } while (0)
504
505 #define ADD_UNOP(op) do {       \
506                 MONO_INST_NEW (cfg, ins, (op)); \
507                 sp--;   \
508                 ins->sreg1 = sp [0]->dreg;      \
509                 type_from_op (cfg, ins, sp [0], NULL);  \
510                 CHECK_TYPE (ins);       \
511         (ins)->dreg = alloc_dreg ((cfg), (ins)->type); \
512         MONO_ADD_INS ((cfg)->cbb, (ins)); \
513                 *sp++ = mono_decompose_opcode (cfg, ins);       \
514         } while (0)
515
516 #define ADD_BINCOND(next_block) do {    \
517                 MonoInst *cmp;  \
518                 sp -= 2; \
519                 MONO_INST_NEW(cfg, cmp, OP_COMPARE);    \
520                 cmp->sreg1 = sp [0]->dreg;      \
521                 cmp->sreg2 = sp [1]->dreg;      \
522                 type_from_op (cfg, cmp, sp [0], sp [1]);        \
523                 CHECK_TYPE (cmp);       \
524                 add_widen_op (cfg, cmp, &sp [0], &sp [1]);                                              \
525                 type_from_op (cfg, ins, sp [0], sp [1]);                                                        \
526                 ins->inst_many_bb = mono_mempool_alloc (cfg->mempool, sizeof(gpointer)*2);      \
527                 GET_BBLOCK (cfg, tblock, target);               \
528                 link_bblock (cfg, cfg->cbb, tblock);    \
529                 ins->inst_true_bb = tblock;     \
530                 if ((next_block)) {     \
531                         link_bblock (cfg, cfg->cbb, (next_block));      \
532                         ins->inst_false_bb = (next_block);      \
533                         start_new_bblock = 1;   \
534                 } else {        \
535                         GET_BBLOCK (cfg, tblock, ip);           \
536                         link_bblock (cfg, cfg->cbb, tblock);    \
537                         ins->inst_false_bb = tblock;    \
538                         start_new_bblock = 2;   \
539                 }       \
540                 if (sp != stack_start) {                                                                        \
541                     handle_stack_args (cfg, stack_start, sp - stack_start); \
542                         CHECK_UNVERIFIABLE (cfg); \
543                 } \
544         MONO_ADD_INS (cfg->cbb, cmp); \
545                 MONO_ADD_INS (cfg->cbb, ins);   \
546         } while (0)
547
548 /* *
549  * link_bblock: Links two basic blocks
550  *
551  * links two basic blocks in the control flow graph, the 'from'
552  * argument is the starting block and the 'to' argument is the block
553  * the control flow ends to after 'from'.
554  */
555 static void
556 link_bblock (MonoCompile *cfg, MonoBasicBlock *from, MonoBasicBlock* to)
557 {
558         MonoBasicBlock **newa;
559         int i, found;
560
561 #if 0
562         if (from->cil_code) {
563                 if (to->cil_code)
564                         printf ("edge from IL%04x to IL_%04x\n", from->cil_code - cfg->cil_code, to->cil_code - cfg->cil_code);
565                 else
566                         printf ("edge from IL%04x to exit\n", from->cil_code - cfg->cil_code);
567         } else {
568                 if (to->cil_code)
569                         printf ("edge from entry to IL_%04x\n", to->cil_code - cfg->cil_code);
570                 else
571                         printf ("edge from entry to exit\n");
572         }
573 #endif
574
575         found = FALSE;
576         for (i = 0; i < from->out_count; ++i) {
577                 if (to == from->out_bb [i]) {
578                         found = TRUE;
579                         break;
580                 }
581         }
582         if (!found) {
583                 newa = mono_mempool_alloc (cfg->mempool, sizeof (gpointer) * (from->out_count + 1));
584                 for (i = 0; i < from->out_count; ++i) {
585                         newa [i] = from->out_bb [i];
586                 }
587                 newa [i] = to;
588                 from->out_count++;
589                 from->out_bb = newa;
590         }
591
592         found = FALSE;
593         for (i = 0; i < to->in_count; ++i) {
594                 if (from == to->in_bb [i]) {
595                         found = TRUE;
596                         break;
597                 }
598         }
599         if (!found) {
600                 newa = mono_mempool_alloc (cfg->mempool, sizeof (gpointer) * (to->in_count + 1));
601                 for (i = 0; i < to->in_count; ++i) {
602                         newa [i] = to->in_bb [i];
603                 }
604                 newa [i] = from;
605                 to->in_count++;
606                 to->in_bb = newa;
607         }
608 }
609
610 void
611 mono_link_bblock (MonoCompile *cfg, MonoBasicBlock *from, MonoBasicBlock* to)
612 {
613         link_bblock (cfg, from, to);
614 }
615
616 /**
617  * mono_find_block_region:
618  *
619  *   We mark each basic block with a region ID. We use that to avoid BB
620  *   optimizations when blocks are in different regions.
621  *
622  * Returns:
623  *   A region token that encodes where this region is, and information
624  *   about the clause owner for this block.
625  *
626  *   The region encodes the try/catch/filter clause that owns this block
627  *   as well as the type.  -1 is a special value that represents a block
628  *   that is in none of try/catch/filter.
629  */
630 static int
631 mono_find_block_region (MonoCompile *cfg, int offset)
632 {
633         MonoMethodHeader *header = cfg->header;
634         MonoExceptionClause *clause;
635         int i;
636
637         for (i = 0; i < header->num_clauses; ++i) {
638                 clause = &header->clauses [i];
639                 if ((clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) && (offset >= clause->data.filter_offset) &&
640                     (offset < (clause->handler_offset)))
641                         return ((i + 1) << 8) | MONO_REGION_FILTER | clause->flags;
642                            
643                 if (MONO_OFFSET_IN_HANDLER (clause, offset)) {
644                         if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY)
645                                 return ((i + 1) << 8) | MONO_REGION_FINALLY | clause->flags;
646                         else if (clause->flags == MONO_EXCEPTION_CLAUSE_FAULT)
647                                 return ((i + 1) << 8) | MONO_REGION_FAULT | clause->flags;
648                         else
649                                 return ((i + 1) << 8) | MONO_REGION_CATCH | clause->flags;
650                 }
651         }
652         for (i = 0; i < header->num_clauses; ++i) {
653                 clause = &header->clauses [i];
654
655                 if (MONO_OFFSET_IN_CLAUSE (clause, offset))
656                         return ((i + 1) << 8) | clause->flags;
657         }
658
659         return -1;
660 }
661
662 static GList*
663 mono_find_final_block (MonoCompile *cfg, unsigned char *ip, unsigned char *target, int type)
664 {
665         MonoMethodHeader *header = cfg->header;
666         MonoExceptionClause *clause;
667         int i;
668         GList *res = NULL;
669
670         for (i = 0; i < header->num_clauses; ++i) {
671                 clause = &header->clauses [i];
672                 if (MONO_OFFSET_IN_CLAUSE (clause, (ip - header->code)) && 
673                     (!MONO_OFFSET_IN_CLAUSE (clause, (target - header->code)))) {
674                         if (clause->flags == type)
675                                 res = g_list_append (res, clause);
676                 }
677         }
678         return res;
679 }
680
681 static void
682 mono_create_spvar_for_region (MonoCompile *cfg, int region)
683 {
684         MonoInst *var;
685
686         var = g_hash_table_lookup (cfg->spvars, GINT_TO_POINTER (region));
687         if (var)
688                 return;
689
690         var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
691         /* prevent it from being register allocated */
692         var->flags |= MONO_INST_VOLATILE;
693
694         g_hash_table_insert (cfg->spvars, GINT_TO_POINTER (region), var);
695 }
696
697 MonoInst *
698 mono_find_exvar_for_offset (MonoCompile *cfg, int offset)
699 {
700         return g_hash_table_lookup (cfg->exvars, GINT_TO_POINTER (offset));
701 }
702
703 static MonoInst*
704 mono_create_exvar_for_offset (MonoCompile *cfg, int offset)
705 {
706         MonoInst *var;
707
708         var = g_hash_table_lookup (cfg->exvars, GINT_TO_POINTER (offset));
709         if (var)
710                 return var;
711
712         var = mono_compile_create_var (cfg, &mono_defaults.object_class->byval_arg, OP_LOCAL);
713         /* prevent it from being register allocated */
714         var->flags |= MONO_INST_VOLATILE;
715
716         g_hash_table_insert (cfg->exvars, GINT_TO_POINTER (offset), var);
717
718         return var;
719 }
720
721 /*
722  * Returns the type used in the eval stack when @type is loaded.
723  * FIXME: return a MonoType/MonoClass for the byref and VALUETYPE cases.
724  */
725 void
726 type_to_eval_stack_type (MonoCompile *cfg, MonoType *type, MonoInst *inst)
727 {
728         MonoClass *klass;
729
730         type = mini_get_underlying_type (type);
731         inst->klass = klass = mono_class_from_mono_type (type);
732         if (type->byref) {
733                 inst->type = STACK_MP;
734                 return;
735         }
736
737 handle_enum:
738         switch (type->type) {
739         case MONO_TYPE_VOID:
740                 inst->type = STACK_INV;
741                 return;
742         case MONO_TYPE_I1:
743         case MONO_TYPE_U1:
744         case MONO_TYPE_I2:
745         case MONO_TYPE_U2:
746         case MONO_TYPE_I4:
747         case MONO_TYPE_U4:
748                 inst->type = STACK_I4;
749                 return;
750         case MONO_TYPE_I:
751         case MONO_TYPE_U:
752         case MONO_TYPE_PTR:
753         case MONO_TYPE_FNPTR:
754                 inst->type = STACK_PTR;
755                 return;
756         case MONO_TYPE_CLASS:
757         case MONO_TYPE_STRING:
758         case MONO_TYPE_OBJECT:
759         case MONO_TYPE_SZARRAY:
760         case MONO_TYPE_ARRAY:    
761                 inst->type = STACK_OBJ;
762                 return;
763         case MONO_TYPE_I8:
764         case MONO_TYPE_U8:
765                 inst->type = STACK_I8;
766                 return;
767         case MONO_TYPE_R4:
768                 inst->type = cfg->r4_stack_type;
769                 break;
770         case MONO_TYPE_R8:
771                 inst->type = STACK_R8;
772                 return;
773         case MONO_TYPE_VALUETYPE:
774                 if (type->data.klass->enumtype) {
775                         type = mono_class_enum_basetype (type->data.klass);
776                         goto handle_enum;
777                 } else {
778                         inst->klass = klass;
779                         inst->type = STACK_VTYPE;
780                         return;
781                 }
782         case MONO_TYPE_TYPEDBYREF:
783                 inst->klass = mono_defaults.typed_reference_class;
784                 inst->type = STACK_VTYPE;
785                 return;
786         case MONO_TYPE_GENERICINST:
787                 type = &type->data.generic_class->container_class->byval_arg;
788                 goto handle_enum;
789         case MONO_TYPE_VAR:
790         case MONO_TYPE_MVAR:
791                 g_assert (cfg->gshared);
792                 if (mini_is_gsharedvt_type (type)) {
793                         g_assert (cfg->gsharedvt);
794                         inst->type = STACK_VTYPE;
795                 } else {
796                         type_to_eval_stack_type (cfg, mini_get_underlying_type (type), inst);
797                 }
798                 return;
799         default:
800                 g_error ("unknown type 0x%02x in eval stack type", type->type);
801         }
802 }
803
804 /*
805  * The following tables are used to quickly validate the IL code in type_from_op ().
806  */
807 static const char
808 bin_num_table [STACK_MAX] [STACK_MAX] = {
809         {STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV},
810         {STACK_INV, STACK_I4,  STACK_INV, STACK_PTR, STACK_INV, STACK_MP,  STACK_INV, STACK_INV},
811         {STACK_INV, STACK_INV, STACK_I8,  STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV},
812         {STACK_INV, STACK_PTR, STACK_INV, STACK_PTR, STACK_INV, STACK_MP,  STACK_INV, STACK_INV},
813         {STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_R8,  STACK_INV, STACK_INV, STACK_INV, STACK_R8},
814         {STACK_INV, STACK_MP,  STACK_INV, STACK_MP,  STACK_INV, STACK_PTR, STACK_INV, STACK_INV},
815         {STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV},
816         {STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV},
817         {STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_R8, STACK_INV, STACK_INV, STACK_INV, STACK_R4}
818 };
819
820 static const char 
821 neg_table [] = {
822         STACK_INV, STACK_I4, STACK_I8, STACK_PTR, STACK_R8, STACK_INV, STACK_INV, STACK_INV, STACK_R4
823 };
824
825 /* reduce the size of this table */
826 static const char
827 bin_int_table [STACK_MAX] [STACK_MAX] = {
828         {STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV},
829         {STACK_INV, STACK_I4,  STACK_INV, STACK_PTR, STACK_INV, STACK_INV, STACK_INV, STACK_INV},
830         {STACK_INV, STACK_INV, STACK_I8,  STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV},
831         {STACK_INV, STACK_PTR, STACK_INV, STACK_PTR, STACK_INV, STACK_INV, STACK_INV, STACK_INV},
832         {STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV},
833         {STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV},
834         {STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV},
835         {STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV}
836 };
837
838 static const char
839 bin_comp_table [STACK_MAX] [STACK_MAX] = {
840 /*      Inv i  L  p  F  &  O  vt r4 */
841         {0},
842         {0, 1, 0, 1, 0, 0, 0, 0}, /* i, int32 */
843         {0, 0, 1, 0, 0, 0, 0, 0}, /* L, int64 */
844         {0, 1, 0, 1, 0, 2, 4, 0}, /* p, ptr */
845         {0, 0, 0, 0, 1, 0, 0, 0, 1}, /* F, R8 */
846         {0, 0, 0, 2, 0, 1, 0, 0}, /* &, managed pointer */
847         {0, 0, 0, 4, 0, 0, 3, 0}, /* O, reference */
848         {0, 0, 0, 0, 0, 0, 0, 0}, /* vt value type */
849         {0, 0, 0, 0, 1, 0, 0, 0, 1}, /* r, r4 */
850 };
851
852 /* reduce the size of this table */
853 static const char
854 shift_table [STACK_MAX] [STACK_MAX] = {
855         {STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV},
856         {STACK_INV, STACK_I4,  STACK_INV, STACK_I4,  STACK_INV, STACK_INV, STACK_INV, STACK_INV},
857         {STACK_INV, STACK_I8,  STACK_INV, STACK_I8,  STACK_INV, STACK_INV, STACK_INV, STACK_INV},
858         {STACK_INV, STACK_PTR, STACK_INV, STACK_PTR, STACK_INV, STACK_INV, STACK_INV, STACK_INV},
859         {STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV},
860         {STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV},
861         {STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV},
862         {STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV, STACK_INV}
863 };
864
865 /*
866  * Tables to map from the non-specific opcode to the matching
867  * type-specific opcode.
868  */
869 /* handles from CEE_ADD to CEE_SHR_UN (CEE_REM_UN for floats) */
870 static const guint16
871 binops_op_map [STACK_MAX] = {
872         0, OP_IADD-CEE_ADD, OP_LADD-CEE_ADD, OP_PADD-CEE_ADD, OP_FADD-CEE_ADD, OP_PADD-CEE_ADD, 0, 0, OP_RADD-CEE_ADD
873 };
874
875 /* handles from CEE_NEG to CEE_CONV_U8 */
876 static const guint16
877 unops_op_map [STACK_MAX] = {
878         0, OP_INEG-CEE_NEG, OP_LNEG-CEE_NEG, OP_PNEG-CEE_NEG, OP_FNEG-CEE_NEG, OP_PNEG-CEE_NEG, 0, 0, OP_RNEG-CEE_NEG
879 };
880
881 /* handles from CEE_CONV_U2 to CEE_SUB_OVF_UN */
882 static const guint16
883 ovfops_op_map [STACK_MAX] = {
884         0, OP_ICONV_TO_U2-CEE_CONV_U2, OP_LCONV_TO_U2-CEE_CONV_U2, OP_PCONV_TO_U2-CEE_CONV_U2, OP_FCONV_TO_U2-CEE_CONV_U2, OP_PCONV_TO_U2-CEE_CONV_U2, OP_PCONV_TO_U2-CEE_CONV_U2, 0, OP_RCONV_TO_U2-CEE_CONV_U2
885 };
886
887 /* handles from CEE_CONV_OVF_I1_UN to CEE_CONV_OVF_U_UN */
888 static const guint16
889 ovf2ops_op_map [STACK_MAX] = {
890         0, OP_ICONV_TO_OVF_I1_UN-CEE_CONV_OVF_I1_UN, OP_LCONV_TO_OVF_I1_UN-CEE_CONV_OVF_I1_UN, OP_PCONV_TO_OVF_I1_UN-CEE_CONV_OVF_I1_UN, OP_FCONV_TO_OVF_I1_UN-CEE_CONV_OVF_I1_UN, OP_PCONV_TO_OVF_I1_UN-CEE_CONV_OVF_I1_UN, 0, 0, OP_RCONV_TO_OVF_I1_UN-CEE_CONV_OVF_I1_UN
891 };
892
893 /* handles from CEE_CONV_OVF_I1 to CEE_CONV_OVF_U8 */
894 static const guint16
895 ovf3ops_op_map [STACK_MAX] = {
896         0, OP_ICONV_TO_OVF_I1-CEE_CONV_OVF_I1, OP_LCONV_TO_OVF_I1-CEE_CONV_OVF_I1, OP_PCONV_TO_OVF_I1-CEE_CONV_OVF_I1, OP_FCONV_TO_OVF_I1-CEE_CONV_OVF_I1, OP_PCONV_TO_OVF_I1-CEE_CONV_OVF_I1, 0, 0, OP_RCONV_TO_OVF_I1-CEE_CONV_OVF_I1
897 };
898
899 /* handles from CEE_BEQ to CEE_BLT_UN */
900 static const guint16
901 beqops_op_map [STACK_MAX] = {
902         0, OP_IBEQ-CEE_BEQ, OP_LBEQ-CEE_BEQ, OP_PBEQ-CEE_BEQ, OP_FBEQ-CEE_BEQ, OP_PBEQ-CEE_BEQ, OP_PBEQ-CEE_BEQ, 0, OP_FBEQ-CEE_BEQ
903 };
904
905 /* handles from CEE_CEQ to CEE_CLT_UN */
906 static const guint16
907 ceqops_op_map [STACK_MAX] = {
908         0, OP_ICEQ-OP_CEQ, OP_LCEQ-OP_CEQ, OP_PCEQ-OP_CEQ, OP_FCEQ-OP_CEQ, OP_PCEQ-OP_CEQ, OP_PCEQ-OP_CEQ, 0, OP_RCEQ-OP_CEQ
909 };
910
911 /*
912  * Sets ins->type (the type on the eval stack) according to the
913  * type of the opcode and the arguments to it.
914  * Invalid IL code is marked by setting ins->type to the invalid value STACK_INV.
915  *
916  * FIXME: this function sets ins->type unconditionally in some cases, but
917  * it should set it to invalid for some types (a conv.x on an object)
918  */
919 static void
920 type_from_op (MonoCompile *cfg, MonoInst *ins, MonoInst *src1, MonoInst *src2)
921 {
922         switch (ins->opcode) {
923         /* binops */
924         case CEE_ADD:
925         case CEE_SUB:
926         case CEE_MUL:
927         case CEE_DIV:
928         case CEE_REM:
929                 /* FIXME: check unverifiable args for STACK_MP */
930                 ins->type = bin_num_table [src1->type] [src2->type];
931                 ins->opcode += binops_op_map [ins->type];
932                 break;
933         case CEE_DIV_UN:
934         case CEE_REM_UN:
935         case CEE_AND:
936         case CEE_OR:
937         case CEE_XOR:
938                 ins->type = bin_int_table [src1->type] [src2->type];
939                 ins->opcode += binops_op_map [ins->type];
940                 break;
941         case CEE_SHL:
942         case CEE_SHR:
943         case CEE_SHR_UN:
944                 ins->type = shift_table [src1->type] [src2->type];
945                 ins->opcode += binops_op_map [ins->type];
946                 break;
947         case OP_COMPARE:
948         case OP_LCOMPARE:
949         case OP_ICOMPARE:
950                 ins->type = bin_comp_table [src1->type] [src2->type] ? STACK_I4: STACK_INV;
951                 if ((src1->type == STACK_I8) || ((SIZEOF_VOID_P == 8) && ((src1->type == STACK_PTR) || (src1->type == STACK_OBJ) || (src1->type == STACK_MP))))
952                         ins->opcode = OP_LCOMPARE;
953                 else if (src1->type == STACK_R4)
954                         ins->opcode = OP_RCOMPARE;
955                 else if (src1->type == STACK_R8)
956                         ins->opcode = OP_FCOMPARE;
957                 else
958                         ins->opcode = OP_ICOMPARE;
959                 break;
960         case OP_ICOMPARE_IMM:
961                 ins->type = bin_comp_table [src1->type] [src1->type] ? STACK_I4 : STACK_INV;
962                 if ((src1->type == STACK_I8) || ((SIZEOF_VOID_P == 8) && ((src1->type == STACK_PTR) || (src1->type == STACK_OBJ) || (src1->type == STACK_MP))))
963                         ins->opcode = OP_LCOMPARE_IMM;          
964                 break;
965         case CEE_BEQ:
966         case CEE_BGE:
967         case CEE_BGT:
968         case CEE_BLE:
969         case CEE_BLT:
970         case CEE_BNE_UN:
971         case CEE_BGE_UN:
972         case CEE_BGT_UN:
973         case CEE_BLE_UN:
974         case CEE_BLT_UN:
975                 ins->opcode += beqops_op_map [src1->type];
976                 break;
977         case OP_CEQ:
978                 ins->type = bin_comp_table [src1->type] [src2->type] ? STACK_I4: STACK_INV;
979                 ins->opcode += ceqops_op_map [src1->type];
980                 break;
981         case OP_CGT:
982         case OP_CGT_UN:
983         case OP_CLT:
984         case OP_CLT_UN:
985                 ins->type = (bin_comp_table [src1->type] [src2->type] & 1) ? STACK_I4: STACK_INV;
986                 ins->opcode += ceqops_op_map [src1->type];
987                 break;
988         /* unops */
989         case CEE_NEG:
990                 ins->type = neg_table [src1->type];
991                 ins->opcode += unops_op_map [ins->type];
992                 break;
993         case CEE_NOT:
994                 if (src1->type >= STACK_I4 && src1->type <= STACK_PTR)
995                         ins->type = src1->type;
996                 else
997                         ins->type = STACK_INV;
998                 ins->opcode += unops_op_map [ins->type];
999                 break;
1000         case CEE_CONV_I1:
1001         case CEE_CONV_I2:
1002         case CEE_CONV_I4:
1003         case CEE_CONV_U4:
1004                 ins->type = STACK_I4;
1005                 ins->opcode += unops_op_map [src1->type];
1006                 break;
1007         case CEE_CONV_R_UN:
1008                 ins->type = STACK_R8;
1009                 switch (src1->type) {
1010                 case STACK_I4:
1011                 case STACK_PTR:
1012                         ins->opcode = OP_ICONV_TO_R_UN;
1013                         break;
1014                 case STACK_I8:
1015                         ins->opcode = OP_LCONV_TO_R_UN; 
1016                         break;
1017                 }
1018                 break;
1019         case CEE_CONV_OVF_I1:
1020         case CEE_CONV_OVF_U1:
1021         case CEE_CONV_OVF_I2:
1022         case CEE_CONV_OVF_U2:
1023         case CEE_CONV_OVF_I4:
1024         case CEE_CONV_OVF_U4:
1025                 ins->type = STACK_I4;
1026                 ins->opcode += ovf3ops_op_map [src1->type];
1027                 break;
1028         case CEE_CONV_OVF_I_UN:
1029         case CEE_CONV_OVF_U_UN:
1030                 ins->type = STACK_PTR;
1031                 ins->opcode += ovf2ops_op_map [src1->type];
1032                 break;
1033         case CEE_CONV_OVF_I1_UN:
1034         case CEE_CONV_OVF_I2_UN:
1035         case CEE_CONV_OVF_I4_UN:
1036         case CEE_CONV_OVF_U1_UN:
1037         case CEE_CONV_OVF_U2_UN:
1038         case CEE_CONV_OVF_U4_UN:
1039                 ins->type = STACK_I4;
1040                 ins->opcode += ovf2ops_op_map [src1->type];
1041                 break;
1042         case CEE_CONV_U:
1043                 ins->type = STACK_PTR;
1044                 switch (src1->type) {
1045                 case STACK_I4:
1046                         ins->opcode = OP_ICONV_TO_U;
1047                         break;
1048                 case STACK_PTR:
1049                 case STACK_MP:
1050 #if SIZEOF_VOID_P == 8
1051                         ins->opcode = OP_LCONV_TO_U;
1052 #else
1053                         ins->opcode = OP_MOVE;
1054 #endif
1055                         break;
1056                 case STACK_I8:
1057                         ins->opcode = OP_LCONV_TO_U;
1058                         break;
1059                 case STACK_R8:
1060                         ins->opcode = OP_FCONV_TO_U;
1061                         break;
1062                 }
1063                 break;
1064         case CEE_CONV_I8:
1065         case CEE_CONV_U8:
1066                 ins->type = STACK_I8;
1067                 ins->opcode += unops_op_map [src1->type];
1068                 break;
1069         case CEE_CONV_OVF_I8:
1070         case CEE_CONV_OVF_U8:
1071                 ins->type = STACK_I8;
1072                 ins->opcode += ovf3ops_op_map [src1->type];
1073                 break;
1074         case CEE_CONV_OVF_U8_UN:
1075         case CEE_CONV_OVF_I8_UN:
1076                 ins->type = STACK_I8;
1077                 ins->opcode += ovf2ops_op_map [src1->type];
1078                 break;
1079         case CEE_CONV_R4:
1080                 ins->type = cfg->r4_stack_type;
1081                 ins->opcode += unops_op_map [src1->type];
1082                 break;
1083         case CEE_CONV_R8:
1084                 ins->type = STACK_R8;
1085                 ins->opcode += unops_op_map [src1->type];
1086                 break;
1087         case OP_CKFINITE:
1088                 ins->type = STACK_R8;           
1089                 break;
1090         case CEE_CONV_U2:
1091         case CEE_CONV_U1:
1092                 ins->type = STACK_I4;
1093                 ins->opcode += ovfops_op_map [src1->type];
1094                 break;
1095         case CEE_CONV_I:
1096         case CEE_CONV_OVF_I:
1097         case CEE_CONV_OVF_U:
1098                 ins->type = STACK_PTR;
1099                 ins->opcode += ovfops_op_map [src1->type];
1100                 break;
1101         case CEE_ADD_OVF:
1102         case CEE_ADD_OVF_UN:
1103         case CEE_MUL_OVF:
1104         case CEE_MUL_OVF_UN:
1105         case CEE_SUB_OVF:
1106         case CEE_SUB_OVF_UN:
1107                 ins->type = bin_num_table [src1->type] [src2->type];
1108                 ins->opcode += ovfops_op_map [src1->type];
1109                 if (ins->type == STACK_R8)
1110                         ins->type = STACK_INV;
1111                 break;
1112         case OP_LOAD_MEMBASE:
1113                 ins->type = STACK_PTR;
1114                 break;
1115         case OP_LOADI1_MEMBASE:
1116         case OP_LOADU1_MEMBASE:
1117         case OP_LOADI2_MEMBASE:
1118         case OP_LOADU2_MEMBASE:
1119         case OP_LOADI4_MEMBASE:
1120         case OP_LOADU4_MEMBASE:
1121                 ins->type = STACK_PTR;
1122                 break;
1123         case OP_LOADI8_MEMBASE:
1124                 ins->type = STACK_I8;
1125                 break;
1126         case OP_LOADR4_MEMBASE:
1127                 ins->type = cfg->r4_stack_type;
1128                 break;
1129         case OP_LOADR8_MEMBASE:
1130                 ins->type = STACK_R8;
1131                 break;
1132         default:
1133                 g_error ("opcode 0x%04x not handled in type from op", ins->opcode);
1134                 break;
1135         }
1136
1137         if (ins->type == STACK_MP)
1138                 ins->klass = mono_defaults.object_class;
1139 }
1140
1141 static const char 
1142 ldind_type [] = {
1143         STACK_I4, STACK_I4, STACK_I4, STACK_I4, STACK_I4, STACK_I4, STACK_I8, STACK_PTR, STACK_R8, STACK_R8, STACK_OBJ
1144 };
1145
1146 #if 0
1147
1148 static const char
1149 param_table [STACK_MAX] [STACK_MAX] = {
1150         {0},
1151 };
1152
1153 static int
1154 check_values_to_signature (MonoInst *args, MonoType *this_ins, MonoMethodSignature *sig)
1155 {
1156         int i;
1157
1158         if (sig->hasthis) {
1159                 switch (args->type) {
1160                 case STACK_I4:
1161                 case STACK_I8:
1162                 case STACK_R8:
1163                 case STACK_VTYPE:
1164                 case STACK_INV:
1165                         return 0;
1166                 }
1167                 args++;
1168         }
1169         for (i = 0; i < sig->param_count; ++i) {
1170                 switch (args [i].type) {
1171                 case STACK_INV:
1172                         return 0;
1173                 case STACK_MP:
1174                         if (!sig->params [i]->byref)
1175                                 return 0;
1176                         continue;
1177                 case STACK_OBJ:
1178                         if (sig->params [i]->byref)
1179                                 return 0;
1180                         switch (sig->params [i]->type) {
1181                         case MONO_TYPE_CLASS:
1182                         case MONO_TYPE_STRING:
1183                         case MONO_TYPE_OBJECT:
1184                         case MONO_TYPE_SZARRAY:
1185                         case MONO_TYPE_ARRAY:
1186                                 break;
1187                         default:
1188                                 return 0;
1189                         }
1190                         continue;
1191                 case STACK_R8:
1192                         if (sig->params [i]->byref)
1193                                 return 0;
1194                         if (sig->params [i]->type != MONO_TYPE_R4 && sig->params [i]->type != MONO_TYPE_R8)
1195                                 return 0;
1196                         continue;
1197                 case STACK_PTR:
1198                 case STACK_I4:
1199                 case STACK_I8:
1200                 case STACK_VTYPE:
1201                         break;
1202                 }
1203                 /*if (!param_table [args [i].type] [sig->params [i]->type])
1204                         return 0;*/
1205         }
1206         return 1;
1207 }
1208 #endif
1209
1210 /*
1211  * When we need a pointer to the current domain many times in a method, we
1212  * call mono_domain_get() once and we store the result in a local variable.
1213  * This function returns the variable that represents the MonoDomain*.
1214  */
1215 inline static MonoInst *
1216 mono_get_domainvar (MonoCompile *cfg)
1217 {
1218         if (!cfg->domainvar)
1219                 cfg->domainvar = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
1220         return cfg->domainvar;
1221 }
1222
1223 /*
1224  * The got_var contains the address of the Global Offset Table when AOT 
1225  * compiling.
1226  */
1227 MonoInst *
1228 mono_get_got_var (MonoCompile *cfg)
1229 {
1230         if (!cfg->compile_aot || !cfg->backend->need_got_var)
1231                 return NULL;
1232         if (!cfg->got_var) {
1233                 cfg->got_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
1234         }
1235         return cfg->got_var;
1236 }
1237
1238 static MonoInst *
1239 mono_get_vtable_var (MonoCompile *cfg)
1240 {
1241         g_assert (cfg->gshared);
1242
1243         if (!cfg->rgctx_var) {
1244                 cfg->rgctx_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
1245                 /* force the var to be stack allocated */
1246                 cfg->rgctx_var->flags |= MONO_INST_VOLATILE;
1247         }
1248
1249         return cfg->rgctx_var;
1250 }
1251
1252 static MonoType*
1253 type_from_stack_type (MonoInst *ins) {
1254         switch (ins->type) {
1255         case STACK_I4: return &mono_defaults.int32_class->byval_arg;
1256         case STACK_I8: return &mono_defaults.int64_class->byval_arg;
1257         case STACK_PTR: return &mono_defaults.int_class->byval_arg;
1258         case STACK_R4: return &mono_defaults.single_class->byval_arg;
1259         case STACK_R8: return &mono_defaults.double_class->byval_arg;
1260         case STACK_MP:
1261                 return &ins->klass->this_arg;
1262         case STACK_OBJ: return &mono_defaults.object_class->byval_arg;
1263         case STACK_VTYPE: return &ins->klass->byval_arg;
1264         default:
1265                 g_error ("stack type %d to monotype not handled\n", ins->type);
1266         }
1267         return NULL;
1268 }
1269
1270 static G_GNUC_UNUSED int
1271 type_to_stack_type (MonoCompile *cfg, MonoType *t)
1272 {
1273         t = mono_type_get_underlying_type (t);
1274         switch (t->type) {
1275         case MONO_TYPE_I1:
1276         case MONO_TYPE_U1:
1277         case MONO_TYPE_I2:
1278         case MONO_TYPE_U2:
1279         case MONO_TYPE_I4:
1280         case MONO_TYPE_U4:
1281                 return STACK_I4;
1282         case MONO_TYPE_I:
1283         case MONO_TYPE_U:
1284         case MONO_TYPE_PTR:
1285         case MONO_TYPE_FNPTR:
1286                 return STACK_PTR;
1287         case MONO_TYPE_CLASS:
1288         case MONO_TYPE_STRING:
1289         case MONO_TYPE_OBJECT:
1290         case MONO_TYPE_SZARRAY:
1291         case MONO_TYPE_ARRAY:    
1292                 return STACK_OBJ;
1293         case MONO_TYPE_I8:
1294         case MONO_TYPE_U8:
1295                 return STACK_I8;
1296         case MONO_TYPE_R4:
1297                 return cfg->r4_stack_type;
1298         case MONO_TYPE_R8:
1299                 return STACK_R8;
1300         case MONO_TYPE_VALUETYPE:
1301         case MONO_TYPE_TYPEDBYREF:
1302                 return STACK_VTYPE;
1303         case MONO_TYPE_GENERICINST:
1304                 if (mono_type_generic_inst_is_valuetype (t))
1305                         return STACK_VTYPE;
1306                 else
1307                         return STACK_OBJ;
1308                 break;
1309         default:
1310                 g_assert_not_reached ();
1311         }
1312
1313         return -1;
1314 }
1315
1316 static MonoClass*
1317 array_access_to_klass (int opcode)
1318 {
1319         switch (opcode) {
1320         case CEE_LDELEM_U1:
1321                 return mono_defaults.byte_class;
1322         case CEE_LDELEM_U2:
1323                 return mono_defaults.uint16_class;
1324         case CEE_LDELEM_I:
1325         case CEE_STELEM_I:
1326                 return mono_defaults.int_class;
1327         case CEE_LDELEM_I1:
1328         case CEE_STELEM_I1:
1329                 return mono_defaults.sbyte_class;
1330         case CEE_LDELEM_I2:
1331         case CEE_STELEM_I2:
1332                 return mono_defaults.int16_class;
1333         case CEE_LDELEM_I4:
1334         case CEE_STELEM_I4:
1335                 return mono_defaults.int32_class;
1336         case CEE_LDELEM_U4:
1337                 return mono_defaults.uint32_class;
1338         case CEE_LDELEM_I8:
1339         case CEE_STELEM_I8:
1340                 return mono_defaults.int64_class;
1341         case CEE_LDELEM_R4:
1342         case CEE_STELEM_R4:
1343                 return mono_defaults.single_class;
1344         case CEE_LDELEM_R8:
1345         case CEE_STELEM_R8:
1346                 return mono_defaults.double_class;
1347         case CEE_LDELEM_REF:
1348         case CEE_STELEM_REF:
1349                 return mono_defaults.object_class;
1350         default:
1351                 g_assert_not_reached ();
1352         }
1353         return NULL;
1354 }
1355
1356 /*
1357  * We try to share variables when possible
1358  */
1359 static MonoInst *
1360 mono_compile_get_interface_var (MonoCompile *cfg, int slot, MonoInst *ins)
1361 {
1362         MonoInst *res;
1363         int pos, vnum;
1364
1365         /* inlining can result in deeper stacks */ 
1366         if (slot >= cfg->header->max_stack)
1367                 return mono_compile_create_var (cfg, type_from_stack_type (ins), OP_LOCAL);
1368
1369         pos = ins->type - 1 + slot * STACK_MAX;
1370
1371         switch (ins->type) {
1372         case STACK_I4:
1373         case STACK_I8:
1374         case STACK_R8:
1375         case STACK_PTR:
1376         case STACK_MP:
1377         case STACK_OBJ:
1378                 if ((vnum = cfg->intvars [pos]))
1379                         return cfg->varinfo [vnum];
1380                 res = mono_compile_create_var (cfg, type_from_stack_type (ins), OP_LOCAL);
1381                 cfg->intvars [pos] = res->inst_c0;
1382                 break;
1383         default:
1384                 res = mono_compile_create_var (cfg, type_from_stack_type (ins), OP_LOCAL);
1385         }
1386         return res;
1387 }
1388
1389 static void
1390 mono_save_token_info (MonoCompile *cfg, MonoImage *image, guint32 token, gpointer key)
1391 {
1392         /* 
1393          * Don't use this if a generic_context is set, since that means AOT can't
1394          * look up the method using just the image+token.
1395          * table == 0 means this is a reference made from a wrapper.
1396          */
1397         if (cfg->compile_aot && !cfg->generic_context && (mono_metadata_token_table (token) > 0)) {
1398                 MonoJumpInfoToken *jump_info_token = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoJumpInfoToken));
1399                 jump_info_token->image = image;
1400                 jump_info_token->token = token;
1401                 g_hash_table_insert (cfg->token_info_hash, key, jump_info_token);
1402         }
1403 }
1404
1405 /*
1406  * This function is called to handle items that are left on the evaluation stack
1407  * at basic block boundaries. What happens is that we save the values to local variables
1408  * and we reload them later when first entering the target basic block (with the
1409  * handle_loaded_temps () function).
1410  * A single joint point will use the same variables (stored in the array bb->out_stack or
1411  * bb->in_stack, if the basic block is before or after the joint point).
1412  *
1413  * This function needs to be called _before_ emitting the last instruction of
1414  * the bb (i.e. before emitting a branch).
1415  * If the stack merge fails at a join point, cfg->unverifiable is set.
1416  */
1417 static void
1418 handle_stack_args (MonoCompile *cfg, MonoInst **sp, int count)
1419 {
1420         int i, bindex;
1421         MonoBasicBlock *bb = cfg->cbb;
1422         MonoBasicBlock *outb;
1423         MonoInst *inst, **locals;
1424         gboolean found;
1425
1426         if (!count)
1427                 return;
1428         if (cfg->verbose_level > 3)
1429                 printf ("%d item(s) on exit from B%d\n", count, bb->block_num);
1430         if (!bb->out_scount) {
1431                 bb->out_scount = count;
1432                 //printf ("bblock %d has out:", bb->block_num);
1433                 found = FALSE;
1434                 for (i = 0; i < bb->out_count; ++i) {
1435                         outb = bb->out_bb [i];
1436                         /* exception handlers are linked, but they should not be considered for stack args */
1437                         if (outb->flags & BB_EXCEPTION_HANDLER)
1438                                 continue;
1439                         //printf (" %d", outb->block_num);
1440                         if (outb->in_stack) {
1441                                 found = TRUE;
1442                                 bb->out_stack = outb->in_stack;
1443                                 break;
1444                         }
1445                 }
1446                 //printf ("\n");
1447                 if (!found) {
1448                         bb->out_stack = mono_mempool_alloc (cfg->mempool, sizeof (MonoInst*) * count);
1449                         for (i = 0; i < count; ++i) {
1450                                 /* 
1451                                  * try to reuse temps already allocated for this purpouse, if they occupy the same
1452                                  * stack slot and if they are of the same type.
1453                                  * This won't cause conflicts since if 'local' is used to 
1454                                  * store one of the values in the in_stack of a bblock, then
1455                                  * the same variable will be used for the same outgoing stack 
1456                                  * slot as well. 
1457                                  * This doesn't work when inlining methods, since the bblocks
1458                                  * in the inlined methods do not inherit their in_stack from
1459                                  * the bblock they are inlined to. See bug #58863 for an
1460                                  * example.
1461                                  */
1462                                 if (cfg->inlined_method)
1463                                         bb->out_stack [i] = mono_compile_create_var (cfg, type_from_stack_type (sp [i]), OP_LOCAL);
1464                                 else
1465                                         bb->out_stack [i] = mono_compile_get_interface_var (cfg, i, sp [i]);
1466                         }
1467                 }
1468         }
1469
1470         for (i = 0; i < bb->out_count; ++i) {
1471                 outb = bb->out_bb [i];
1472                 /* exception handlers are linked, but they should not be considered for stack args */
1473                 if (outb->flags & BB_EXCEPTION_HANDLER)
1474                         continue;
1475                 if (outb->in_scount) {
1476                         if (outb->in_scount != bb->out_scount) {
1477                                 cfg->unverifiable = TRUE;
1478                                 return;
1479                         }
1480                         continue; /* check they are the same locals */
1481                 }
1482                 outb->in_scount = count;
1483                 outb->in_stack = bb->out_stack;
1484         }
1485
1486         locals = bb->out_stack;
1487         cfg->cbb = bb;
1488         for (i = 0; i < count; ++i) {
1489                 EMIT_NEW_TEMPSTORE (cfg, inst, locals [i]->inst_c0, sp [i]);
1490                 inst->cil_code = sp [i]->cil_code;
1491                 sp [i] = locals [i];
1492                 if (cfg->verbose_level > 3)
1493                         printf ("storing %d to temp %d\n", i, (int)locals [i]->inst_c0);
1494         }
1495
1496         /*
1497          * It is possible that the out bblocks already have in_stack assigned, and
1498          * the in_stacks differ. In this case, we will store to all the different 
1499          * in_stacks.
1500          */
1501
1502         found = TRUE;
1503         bindex = 0;
1504         while (found) {
1505                 /* Find a bblock which has a different in_stack */
1506                 found = FALSE;
1507                 while (bindex < bb->out_count) {
1508                         outb = bb->out_bb [bindex];
1509                         /* exception handlers are linked, but they should not be considered for stack args */
1510                         if (outb->flags & BB_EXCEPTION_HANDLER) {
1511                                 bindex++;
1512                                 continue;
1513                         }
1514                         if (outb->in_stack != locals) {
1515                                 for (i = 0; i < count; ++i) {
1516                                         EMIT_NEW_TEMPSTORE (cfg, inst, outb->in_stack [i]->inst_c0, sp [i]);
1517                                         inst->cil_code = sp [i]->cil_code;
1518                                         sp [i] = locals [i];
1519                                         if (cfg->verbose_level > 3)
1520                                                 printf ("storing %d to temp %d\n", i, (int)outb->in_stack [i]->inst_c0);
1521                                 }
1522                                 locals = outb->in_stack;
1523                                 found = TRUE;
1524                                 break;
1525                         }
1526                         bindex ++;
1527                 }
1528         }
1529 }
1530
1531 static void
1532 mini_emit_interface_bitmap_check (MonoCompile *cfg, int intf_bit_reg, int base_reg, int offset, MonoClass *klass)
1533 {
1534         int ibitmap_reg = alloc_preg (cfg);
1535 #ifdef COMPRESSED_INTERFACE_BITMAP
1536         MonoInst *args [2];
1537         MonoInst *res, *ins;
1538         NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, ibitmap_reg, base_reg, offset);
1539         MONO_ADD_INS (cfg->cbb, ins);
1540         args [0] = ins;
1541         if (cfg->compile_aot)
1542                 EMIT_NEW_AOTCONST (cfg, args [1], MONO_PATCH_INFO_IID, klass);
1543         else
1544                 EMIT_NEW_ICONST (cfg, args [1], klass->interface_id);
1545         res = mono_emit_jit_icall (cfg, mono_class_interface_match, args);
1546         MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, intf_bit_reg, res->dreg);
1547 #else
1548         int ibitmap_byte_reg = alloc_preg (cfg);
1549
1550         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, ibitmap_reg, base_reg, offset);
1551
1552         if (cfg->compile_aot) {
1553                 int iid_reg = alloc_preg (cfg);
1554                 int shifted_iid_reg = alloc_preg (cfg);
1555                 int ibitmap_byte_address_reg = alloc_preg (cfg);
1556                 int masked_iid_reg = alloc_preg (cfg);
1557                 int iid_one_bit_reg = alloc_preg (cfg);
1558                 int iid_bit_reg = alloc_preg (cfg);
1559                 MONO_EMIT_NEW_AOTCONST (cfg, iid_reg, klass, MONO_PATCH_INFO_IID);
1560                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_IMM, shifted_iid_reg, iid_reg, 3);
1561                 MONO_EMIT_NEW_BIALU (cfg, OP_PADD, ibitmap_byte_address_reg, ibitmap_reg, shifted_iid_reg);
1562                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU1_MEMBASE, ibitmap_byte_reg, ibitmap_byte_address_reg, 0);
1563                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, masked_iid_reg, iid_reg, 7);
1564                 MONO_EMIT_NEW_ICONST (cfg, iid_one_bit_reg, 1);
1565                 MONO_EMIT_NEW_BIALU (cfg, OP_ISHL, iid_bit_reg, iid_one_bit_reg, masked_iid_reg);
1566                 MONO_EMIT_NEW_BIALU (cfg, OP_IAND, intf_bit_reg, ibitmap_byte_reg, iid_bit_reg);
1567         } else {
1568                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI1_MEMBASE, ibitmap_byte_reg, ibitmap_reg, klass->interface_id >> 3);
1569                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, intf_bit_reg, ibitmap_byte_reg, 1 << (klass->interface_id & 7));
1570         }
1571 #endif
1572 }
1573
1574 /* 
1575  * Emit code which loads into "intf_bit_reg" a nonzero value if the MonoClass
1576  * stored in "klass_reg" implements the interface "klass".
1577  */
1578 static void
1579 mini_emit_load_intf_bit_reg_class (MonoCompile *cfg, int intf_bit_reg, int klass_reg, MonoClass *klass)
1580 {
1581         mini_emit_interface_bitmap_check (cfg, intf_bit_reg, klass_reg, MONO_STRUCT_OFFSET (MonoClass, interface_bitmap), klass);
1582 }
1583
1584 /* 
1585  * Emit code which loads into "intf_bit_reg" a nonzero value if the MonoVTable
1586  * stored in "vtable_reg" implements the interface "klass".
1587  */
1588 static void
1589 mini_emit_load_intf_bit_reg_vtable (MonoCompile *cfg, int intf_bit_reg, int vtable_reg, MonoClass *klass)
1590 {
1591         mini_emit_interface_bitmap_check (cfg, intf_bit_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, interface_bitmap), klass);
1592 }
1593
1594 /* 
1595  * Emit code which checks whenever the interface id of @klass is smaller than
1596  * than the value given by max_iid_reg.
1597 */
1598 static void
1599 mini_emit_max_iid_check (MonoCompile *cfg, int max_iid_reg, MonoClass *klass,
1600                                                  MonoBasicBlock *false_target)
1601 {
1602         if (cfg->compile_aot) {
1603                 int iid_reg = alloc_preg (cfg);
1604                 MONO_EMIT_NEW_AOTCONST (cfg, iid_reg, klass, MONO_PATCH_INFO_IID);
1605                 MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, max_iid_reg, iid_reg);
1606         }
1607         else
1608                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, max_iid_reg, klass->interface_id);
1609         if (false_target)
1610                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBLT_UN, false_target);
1611         else
1612                 MONO_EMIT_NEW_COND_EXC (cfg, LT_UN, "InvalidCastException");
1613 }
1614
1615 /* Same as above, but obtains max_iid from a vtable */
1616 static void
1617 mini_emit_max_iid_check_vtable (MonoCompile *cfg, int vtable_reg, MonoClass *klass,
1618                                                                  MonoBasicBlock *false_target)
1619 {
1620         int max_iid_reg = alloc_preg (cfg);
1621                 
1622         MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU2_MEMBASE, max_iid_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, max_interface_id));
1623         mini_emit_max_iid_check (cfg, max_iid_reg, klass, false_target);
1624 }
1625
1626 /* Same as above, but obtains max_iid from a klass */
1627 static void
1628 mini_emit_max_iid_check_class (MonoCompile *cfg, int klass_reg, MonoClass *klass,
1629                                                                  MonoBasicBlock *false_target)
1630 {
1631         int max_iid_reg = alloc_preg (cfg);
1632
1633         MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU2_MEMBASE, max_iid_reg, klass_reg, MONO_STRUCT_OFFSET (MonoClass, max_interface_id));
1634         mini_emit_max_iid_check (cfg, max_iid_reg, klass, false_target);
1635 }
1636
1637 static void
1638 mini_emit_isninst_cast_inst (MonoCompile *cfg, int klass_reg, MonoClass *klass, MonoInst *klass_ins, MonoBasicBlock *false_target, MonoBasicBlock *true_target)
1639 {
1640         int idepth_reg = alloc_preg (cfg);
1641         int stypes_reg = alloc_preg (cfg);
1642         int stype = alloc_preg (cfg);
1643
1644         mono_class_setup_supertypes (klass);
1645
1646         if (klass->idepth > MONO_DEFAULT_SUPERTABLE_SIZE) {
1647                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU2_MEMBASE, idepth_reg, klass_reg, MONO_STRUCT_OFFSET (MonoClass, idepth));
1648                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, idepth_reg, klass->idepth);
1649                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBLT_UN, false_target);
1650         }
1651         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, stypes_reg, klass_reg, MONO_STRUCT_OFFSET (MonoClass, supertypes));
1652         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, stype, stypes_reg, ((klass->idepth - 1) * SIZEOF_VOID_P));
1653         if (klass_ins) {
1654                 MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, stype, klass_ins->dreg);
1655         } else if (cfg->compile_aot) {
1656                 int const_reg = alloc_preg (cfg);
1657                 MONO_EMIT_NEW_CLASSCONST (cfg, const_reg, klass);
1658                 MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, stype, const_reg);
1659         } else {
1660                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, stype, klass);
1661         }
1662         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, true_target);
1663 }
1664
1665 static void
1666 mini_emit_isninst_cast (MonoCompile *cfg, int klass_reg, MonoClass *klass, MonoBasicBlock *false_target, MonoBasicBlock *true_target)
1667 {
1668         mini_emit_isninst_cast_inst (cfg, klass_reg, klass, NULL, false_target, true_target);
1669 }
1670
1671 static void
1672 mini_emit_iface_cast (MonoCompile *cfg, int vtable_reg, MonoClass *klass, MonoBasicBlock *false_target, MonoBasicBlock *true_target)
1673 {
1674         int intf_reg = alloc_preg (cfg);
1675
1676         mini_emit_max_iid_check_vtable (cfg, vtable_reg, klass, false_target);
1677         mini_emit_load_intf_bit_reg_vtable (cfg, intf_reg, vtable_reg, klass);
1678         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, intf_reg, 0);
1679         if (true_target)
1680                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, true_target);
1681         else
1682                 MONO_EMIT_NEW_COND_EXC (cfg, EQ, "InvalidCastException");               
1683 }
1684
1685 /*
1686  * Variant of the above that takes a register to the class, not the vtable.
1687  */
1688 static void
1689 mini_emit_iface_class_cast (MonoCompile *cfg, int klass_reg, MonoClass *klass, MonoBasicBlock *false_target, MonoBasicBlock *true_target)
1690 {
1691         int intf_bit_reg = alloc_preg (cfg);
1692
1693         mini_emit_max_iid_check_class (cfg, klass_reg, klass, false_target);
1694         mini_emit_load_intf_bit_reg_class (cfg, intf_bit_reg, klass_reg, klass);
1695         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, intf_bit_reg, 0);
1696         if (true_target)
1697                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, true_target);
1698         else
1699                 MONO_EMIT_NEW_COND_EXC (cfg, EQ, "InvalidCastException");
1700 }
1701
1702 static inline void
1703 mini_emit_class_check_inst (MonoCompile *cfg, int klass_reg, MonoClass *klass, MonoInst *klass_inst)
1704 {
1705         if (klass_inst) {
1706                 MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, klass_reg, klass_inst->dreg);
1707         } else if (cfg->compile_aot) {
1708                 int const_reg = alloc_preg (cfg);
1709                 MONO_EMIT_NEW_CLASSCONST (cfg, const_reg, klass);
1710                 MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, klass_reg, const_reg);
1711         } else {
1712                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, klass_reg, klass);
1713         }
1714         MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "InvalidCastException");
1715 }
1716
1717 static inline void
1718 mini_emit_class_check (MonoCompile *cfg, int klass_reg, MonoClass *klass)
1719 {
1720         mini_emit_class_check_inst (cfg, klass_reg, klass, NULL);
1721 }
1722
1723 static inline void
1724 mini_emit_class_check_branch (MonoCompile *cfg, int klass_reg, MonoClass *klass, int branch_op, MonoBasicBlock *target)
1725 {
1726         if (cfg->compile_aot) {
1727                 int const_reg = alloc_preg (cfg);
1728                 MONO_EMIT_NEW_CLASSCONST (cfg, const_reg, klass);
1729                 MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, klass_reg, const_reg);
1730         } else {
1731                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, klass_reg, klass);
1732         }
1733         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, branch_op, target);
1734 }
1735
1736 static void
1737 mini_emit_castclass (MonoCompile *cfg, int obj_reg, int klass_reg, MonoClass *klass, MonoBasicBlock *object_is_null);
1738         
1739 static void
1740 mini_emit_castclass_inst (MonoCompile *cfg, int obj_reg, int klass_reg, MonoClass *klass, MonoInst *klass_inst, MonoBasicBlock *object_is_null)
1741 {
1742         if (klass->rank) {
1743                 int rank_reg = alloc_preg (cfg);
1744                 int eclass_reg = alloc_preg (cfg);
1745
1746                 g_assert (!klass_inst);
1747                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU1_MEMBASE, rank_reg, klass_reg, MONO_STRUCT_OFFSET (MonoClass, rank));
1748                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, rank_reg, klass->rank);
1749                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "InvalidCastException");
1750                 //              MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, klass));
1751                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, eclass_reg, klass_reg, MONO_STRUCT_OFFSET (MonoClass, cast_class));
1752                 if (klass->cast_class == mono_defaults.object_class) {
1753                         int parent_reg = alloc_preg (cfg);
1754                         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, parent_reg, eclass_reg, MONO_STRUCT_OFFSET (MonoClass, parent));
1755                         mini_emit_class_check_branch (cfg, parent_reg, mono_defaults.enum_class->parent, OP_PBNE_UN, object_is_null);
1756                         mini_emit_class_check (cfg, eclass_reg, mono_defaults.enum_class);
1757                 } else if (klass->cast_class == mono_defaults.enum_class->parent) {
1758                         mini_emit_class_check_branch (cfg, eclass_reg, mono_defaults.enum_class->parent, OP_PBEQ, object_is_null);
1759                         mini_emit_class_check (cfg, eclass_reg, mono_defaults.enum_class);
1760                 } else if (klass->cast_class == mono_defaults.enum_class) {
1761                         mini_emit_class_check (cfg, eclass_reg, mono_defaults.enum_class);
1762                 } else if (klass->cast_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
1763                         mini_emit_iface_class_cast (cfg, eclass_reg, klass->cast_class, NULL, NULL);
1764                 } else {
1765                         // Pass -1 as obj_reg to skip the check below for arrays of arrays
1766                         mini_emit_castclass (cfg, -1, eclass_reg, klass->cast_class, object_is_null);
1767                 }
1768
1769                 if ((klass->rank == 1) && (klass->byval_arg.type == MONO_TYPE_SZARRAY) && (obj_reg != -1)) {
1770                         /* Check that the object is a vector too */
1771                         int bounds_reg = alloc_preg (cfg);
1772                         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, bounds_reg, obj_reg, MONO_STRUCT_OFFSET (MonoArray, bounds));
1773                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, bounds_reg, 0);
1774                         MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "InvalidCastException");
1775                 }
1776         } else {
1777                 int idepth_reg = alloc_preg (cfg);
1778                 int stypes_reg = alloc_preg (cfg);
1779                 int stype = alloc_preg (cfg);
1780
1781                 mono_class_setup_supertypes (klass);
1782
1783                 if (klass->idepth > MONO_DEFAULT_SUPERTABLE_SIZE) {
1784                         MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU2_MEMBASE, idepth_reg, klass_reg, MONO_STRUCT_OFFSET (MonoClass, idepth));
1785                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, idepth_reg, klass->idepth);
1786                         MONO_EMIT_NEW_COND_EXC (cfg, LT_UN, "InvalidCastException");
1787                 }
1788                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, stypes_reg, klass_reg, MONO_STRUCT_OFFSET (MonoClass, supertypes));
1789                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, stype, stypes_reg, ((klass->idepth - 1) * SIZEOF_VOID_P));
1790                 mini_emit_class_check_inst (cfg, stype, klass, klass_inst);
1791         }
1792 }
1793
1794 static void
1795 mini_emit_castclass (MonoCompile *cfg, int obj_reg, int klass_reg, MonoClass *klass, MonoBasicBlock *object_is_null)
1796 {
1797         mini_emit_castclass_inst (cfg, obj_reg, klass_reg, klass, NULL, object_is_null);
1798 }
1799
1800 static void 
1801 mini_emit_memset (MonoCompile *cfg, int destreg, int offset, int size, int val, int align)
1802 {
1803         int val_reg;
1804
1805         g_assert (val == 0);
1806
1807         if (align == 0)
1808                 align = 4;
1809
1810         if ((size <= SIZEOF_REGISTER) && (size <= align)) {
1811                 switch (size) {
1812                 case 1:
1813                         MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STOREI1_MEMBASE_IMM, destreg, offset, val);
1814                         return;
1815                 case 2:
1816                         MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STOREI2_MEMBASE_IMM, destreg, offset, val);
1817                         return;
1818                 case 4:
1819                         MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STOREI4_MEMBASE_IMM, destreg, offset, val);
1820                         return;
1821 #if SIZEOF_REGISTER == 8
1822                 case 8:
1823                         MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STOREI8_MEMBASE_IMM, destreg, offset, val);
1824                         return;
1825 #endif
1826                 }
1827         }
1828
1829         val_reg = alloc_preg (cfg);
1830
1831         if (SIZEOF_REGISTER == 8)
1832                 MONO_EMIT_NEW_I8CONST (cfg, val_reg, val);
1833         else
1834                 MONO_EMIT_NEW_ICONST (cfg, val_reg, val);
1835
1836         if (align < 4) {
1837                 /* This could be optimized further if neccesary */
1838                 while (size >= 1) {
1839                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, destreg, offset, val_reg);
1840                         offset += 1;
1841                         size -= 1;
1842                 }
1843                 return;
1844         }       
1845
1846         if (!cfg->backend->no_unaligned_access && SIZEOF_REGISTER == 8) {
1847                 if (offset % 8) {
1848                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, destreg, offset, val_reg);
1849                         offset += 4;
1850                         size -= 4;
1851                 }
1852                 while (size >= 8) {
1853                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, destreg, offset, val_reg);
1854                         offset += 8;
1855                         size -= 8;
1856                 }
1857         }       
1858
1859         while (size >= 4) {
1860                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, destreg, offset, val_reg);
1861                 offset += 4;
1862                 size -= 4;
1863         }
1864         while (size >= 2) {
1865                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI2_MEMBASE_REG, destreg, offset, val_reg);
1866                 offset += 2;
1867                 size -= 2;
1868         }
1869         while (size >= 1) {
1870                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, destreg, offset, val_reg);
1871                 offset += 1;
1872                 size -= 1;
1873         }
1874 }
1875
1876 void 
1877 mini_emit_memcpy (MonoCompile *cfg, int destreg, int doffset, int srcreg, int soffset, int size, int align)
1878 {
1879         int cur_reg;
1880
1881         if (align == 0)
1882                 align = 4;
1883
1884         /*FIXME arbitrary hack to avoid unbound code expansion.*/
1885         g_assert (size < 10000);
1886
1887         if (align < 4) {
1888                 /* This could be optimized further if neccesary */
1889                 while (size >= 1) {
1890                         cur_reg = alloc_preg (cfg);
1891                         MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI1_MEMBASE, cur_reg, srcreg, soffset);
1892                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, destreg, doffset, cur_reg);
1893                         doffset += 1;
1894                         soffset += 1;
1895                         size -= 1;
1896                 }
1897         }
1898
1899         if (!cfg->backend->no_unaligned_access && SIZEOF_REGISTER == 8) {
1900                 while (size >= 8) {
1901                         cur_reg = alloc_preg (cfg);
1902                         MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI8_MEMBASE, cur_reg, srcreg, soffset);
1903                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, destreg, doffset, cur_reg);
1904                         doffset += 8;
1905                         soffset += 8;
1906                         size -= 8;
1907                 }
1908         }       
1909
1910         while (size >= 4) {
1911                 cur_reg = alloc_preg (cfg);
1912                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, cur_reg, srcreg, soffset);
1913                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, destreg, doffset, cur_reg);
1914                 doffset += 4;
1915                 soffset += 4;
1916                 size -= 4;
1917         }
1918         while (size >= 2) {
1919                 cur_reg = alloc_preg (cfg);
1920                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI2_MEMBASE, cur_reg, srcreg, soffset);
1921                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI2_MEMBASE_REG, destreg, doffset, cur_reg);
1922                 doffset += 2;
1923                 soffset += 2;
1924                 size -= 2;
1925         }
1926         while (size >= 1) {
1927                 cur_reg = alloc_preg (cfg);
1928                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI1_MEMBASE, cur_reg, srcreg, soffset);
1929                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, destreg, doffset, cur_reg);
1930                 doffset += 1;
1931                 soffset += 1;
1932                 size -= 1;
1933         }
1934 }
1935
1936 static void
1937 emit_tls_set (MonoCompile *cfg, int sreg1, int tls_key)
1938 {
1939         MonoInst *ins, *c;
1940
1941         if (cfg->compile_aot) {
1942                 EMIT_NEW_TLS_OFFSETCONST (cfg, c, tls_key);
1943                 MONO_INST_NEW (cfg, ins, OP_TLS_SET_REG);
1944                 ins->sreg1 = sreg1;
1945                 ins->sreg2 = c->dreg;
1946                 MONO_ADD_INS (cfg->cbb, ins);
1947         } else {
1948                 MONO_INST_NEW (cfg, ins, OP_TLS_SET);
1949                 ins->sreg1 = sreg1;
1950                 ins->inst_offset = mini_get_tls_offset (tls_key);
1951                 MONO_ADD_INS (cfg->cbb, ins);
1952         }
1953 }
1954
1955 /*
1956  * emit_push_lmf:
1957  *
1958  *   Emit IR to push the current LMF onto the LMF stack.
1959  */
1960 static void
1961 emit_push_lmf (MonoCompile *cfg)
1962 {
1963         /*
1964          * Emit IR to push the LMF:
1965          * lmf_addr = <lmf_addr from tls>
1966          * lmf->lmf_addr = lmf_addr
1967          * lmf->prev_lmf = *lmf_addr
1968          * *lmf_addr = lmf
1969          */
1970         int lmf_reg, prev_lmf_reg;
1971         MonoInst *ins, *lmf_ins;
1972
1973         if (!cfg->lmf_ir)
1974                 return;
1975
1976         if (cfg->lmf_ir_mono_lmf && mini_tls_get_supported (cfg, TLS_KEY_LMF)) {
1977                 /* Load current lmf */
1978                 lmf_ins = mono_get_lmf_intrinsic (cfg);
1979                 g_assert (lmf_ins);
1980                 MONO_ADD_INS (cfg->cbb, lmf_ins);
1981                 EMIT_NEW_VARLOADA (cfg, ins, cfg->lmf_var, NULL);
1982                 lmf_reg = ins->dreg;
1983                 /* Save previous_lmf */
1984                 EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_reg, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), lmf_ins->dreg);
1985                 /* Set new LMF */
1986                 emit_tls_set (cfg, lmf_reg, TLS_KEY_LMF);
1987         } else {
1988                 /*
1989                  * Store lmf_addr in a variable, so it can be allocated to a global register.
1990                  */
1991                 if (!cfg->lmf_addr_var)
1992                         cfg->lmf_addr_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
1993
1994 #ifdef HOST_WIN32
1995                 ins = mono_get_jit_tls_intrinsic (cfg);
1996                 if (ins) {
1997                         int jit_tls_dreg = ins->dreg;
1998
1999                         MONO_ADD_INS (cfg->cbb, ins);
2000                         lmf_reg = alloc_preg (cfg);
2001                         EMIT_NEW_BIALU_IMM (cfg, lmf_ins, OP_PADD_IMM, lmf_reg, jit_tls_dreg, MONO_STRUCT_OFFSET (MonoJitTlsData, lmf));
2002                 } else {
2003                         lmf_ins = mono_emit_jit_icall (cfg, mono_get_lmf_addr, NULL);
2004                 }
2005 #else
2006                 lmf_ins = mono_get_lmf_addr_intrinsic (cfg);
2007                 if (lmf_ins) {
2008                         MONO_ADD_INS (cfg->cbb, lmf_ins);
2009                 } else {
2010 #ifdef TARGET_IOS
2011                         MonoInst *args [16], *jit_tls_ins, *ins;
2012
2013                         /* Inline mono_get_lmf_addr () */
2014                         /* jit_tls = pthread_getspecific (mono_jit_tls_id); lmf_addr = &jit_tls->lmf; */
2015
2016                         /* Load mono_jit_tls_id */
2017                         if (cfg->compile_aot)
2018                                 EMIT_NEW_AOTCONST (cfg, args [0], MONO_PATCH_INFO_JIT_TLS_ID, NULL);
2019                         else
2020                                 EMIT_NEW_ICONST (cfg, args [0], mono_jit_tls_id);
2021                         /* call pthread_getspecific () */
2022                         jit_tls_ins = mono_emit_jit_icall (cfg, pthread_getspecific, args);
2023                         /* lmf_addr = &jit_tls->lmf */
2024                         EMIT_NEW_BIALU_IMM (cfg, ins, OP_PADD_IMM, cfg->lmf_addr_var->dreg, jit_tls_ins->dreg, MONO_STRUCT_OFFSET (MonoJitTlsData, lmf));
2025                         lmf_ins = ins;
2026 #else
2027                         lmf_ins = mono_emit_jit_icall (cfg, mono_get_lmf_addr, NULL);
2028 #endif
2029                 }
2030 #endif
2031                 lmf_ins->dreg = cfg->lmf_addr_var->dreg;
2032
2033                 EMIT_NEW_VARLOADA (cfg, ins, cfg->lmf_var, NULL);
2034                 lmf_reg = ins->dreg;
2035
2036                 prev_lmf_reg = alloc_preg (cfg);
2037                 /* Save previous_lmf */
2038                 EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, prev_lmf_reg, cfg->lmf_addr_var->dreg, 0);
2039                 EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_reg, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf), prev_lmf_reg);
2040                 /* Set new lmf */
2041                 EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, cfg->lmf_addr_var->dreg, 0, lmf_reg);
2042         }
2043 }
2044
2045 /*
2046  * emit_pop_lmf:
2047  *
2048  *   Emit IR to pop the current LMF from the LMF stack.
2049  */
2050 static void
2051 emit_pop_lmf (MonoCompile *cfg)
2052 {
2053         int lmf_reg, lmf_addr_reg, prev_lmf_reg;
2054         MonoInst *ins;
2055
2056         if (!cfg->lmf_ir)
2057                 return;
2058
2059         EMIT_NEW_VARLOADA (cfg, ins, cfg->lmf_var, NULL);
2060         lmf_reg = ins->dreg;
2061
2062         if (cfg->lmf_ir_mono_lmf && mini_tls_get_supported (cfg, TLS_KEY_LMF)) {
2063                 /* Load previous_lmf */
2064                 prev_lmf_reg = alloc_preg (cfg);
2065                 EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, prev_lmf_reg, lmf_reg, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf));
2066                 /* Set new LMF */
2067                 emit_tls_set (cfg, prev_lmf_reg, TLS_KEY_LMF);
2068         } else {
2069                 /*
2070                  * Emit IR to pop the LMF:
2071                  * *(lmf->lmf_addr) = lmf->prev_lmf
2072                  */
2073                 /* This could be called before emit_push_lmf () */
2074                 if (!cfg->lmf_addr_var)
2075                         cfg->lmf_addr_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
2076                 lmf_addr_reg = cfg->lmf_addr_var->dreg;
2077
2078                 prev_lmf_reg = alloc_preg (cfg);
2079                 EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, prev_lmf_reg, lmf_reg, MONO_STRUCT_OFFSET (MonoLMF, previous_lmf));
2080                 EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, lmf_addr_reg, 0, prev_lmf_reg);
2081         }
2082 }
2083
2084 static void
2085 emit_instrumentation_call (MonoCompile *cfg, void *func)
2086 {
2087         MonoInst *iargs [1];
2088
2089         /*
2090          * Avoid instrumenting inlined methods since it can
2091          * distort profiling results.
2092          */
2093         if (cfg->method != cfg->current_method)
2094                 return;
2095
2096         if (cfg->prof_options & MONO_PROFILE_ENTER_LEAVE) {
2097                 EMIT_NEW_METHODCONST (cfg, iargs [0], cfg->method);
2098                 mono_emit_jit_icall (cfg, func, iargs);
2099         }
2100 }
2101
2102 static int
2103 ret_type_to_call_opcode (MonoCompile *cfg, MonoType *type, int calli, int virt)
2104 {
2105 handle_enum:
2106         type = mini_get_underlying_type (type);
2107         switch (type->type) {
2108         case MONO_TYPE_VOID:
2109                 return calli? OP_VOIDCALL_REG: virt? OP_VOIDCALL_MEMBASE: OP_VOIDCALL;
2110         case MONO_TYPE_I1:
2111         case MONO_TYPE_U1:
2112         case MONO_TYPE_I2:
2113         case MONO_TYPE_U2:
2114         case MONO_TYPE_I4:
2115         case MONO_TYPE_U4:
2116                 return calli? OP_CALL_REG: virt? OP_CALL_MEMBASE: OP_CALL;
2117         case MONO_TYPE_I:
2118         case MONO_TYPE_U:
2119         case MONO_TYPE_PTR:
2120         case MONO_TYPE_FNPTR:
2121                 return calli? OP_CALL_REG: virt? OP_CALL_MEMBASE: OP_CALL;
2122         case MONO_TYPE_CLASS:
2123         case MONO_TYPE_STRING:
2124         case MONO_TYPE_OBJECT:
2125         case MONO_TYPE_SZARRAY:
2126         case MONO_TYPE_ARRAY:    
2127                 return calli? OP_CALL_REG: virt? OP_CALL_MEMBASE: OP_CALL;
2128         case MONO_TYPE_I8:
2129         case MONO_TYPE_U8:
2130                 return calli? OP_LCALL_REG: virt? OP_LCALL_MEMBASE: OP_LCALL;
2131         case MONO_TYPE_R4:
2132                 if (cfg->r4fp)
2133                         return calli? OP_RCALL_REG: virt? OP_RCALL_MEMBASE: OP_RCALL;
2134                 else
2135                         return calli? OP_FCALL_REG: virt? OP_FCALL_MEMBASE: OP_FCALL;
2136         case MONO_TYPE_R8:
2137                 return calli? OP_FCALL_REG: virt? OP_FCALL_MEMBASE: OP_FCALL;
2138         case MONO_TYPE_VALUETYPE:
2139                 if (type->data.klass->enumtype) {
2140                         type = mono_class_enum_basetype (type->data.klass);
2141                         goto handle_enum;
2142                 } else
2143                         return calli? OP_VCALL_REG: virt? OP_VCALL_MEMBASE: OP_VCALL;
2144         case MONO_TYPE_TYPEDBYREF:
2145                 return calli? OP_VCALL_REG: virt? OP_VCALL_MEMBASE: OP_VCALL;
2146         case MONO_TYPE_GENERICINST:
2147                 type = &type->data.generic_class->container_class->byval_arg;
2148                 goto handle_enum;
2149         case MONO_TYPE_VAR:
2150         case MONO_TYPE_MVAR:
2151                 /* gsharedvt */
2152                 return calli? OP_VCALL_REG: virt? OP_VCALL_MEMBASE: OP_VCALL;
2153         default:
2154                 g_error ("unknown type 0x%02x in ret_type_to_call_opcode", type->type);
2155         }
2156         return -1;
2157 }
2158
2159 /*
2160  * target_type_is_incompatible:
2161  * @cfg: MonoCompile context
2162  *
2163  * Check that the item @arg on the evaluation stack can be stored
2164  * in the target type (can be a local, or field, etc).
2165  * The cfg arg can be used to check if we need verification or just
2166  * validity checks.
2167  *
2168  * Returns: non-0 value if arg can't be stored on a target.
2169  */
2170 static int
2171 target_type_is_incompatible (MonoCompile *cfg, MonoType *target, MonoInst *arg)
2172 {
2173         MonoType *simple_type;
2174         MonoClass *klass;
2175
2176         if (target->byref) {
2177                 /* FIXME: check that the pointed to types match */
2178                 if (arg->type == STACK_MP)
2179                         return target->type != MONO_TYPE_I && arg->klass != mono_class_from_mono_type (target);
2180                 if (arg->type == STACK_PTR)
2181                         return 0;
2182                 return 1;
2183         }
2184
2185         simple_type = mini_get_underlying_type (target);
2186         switch (simple_type->type) {
2187         case MONO_TYPE_VOID:
2188                 return 1;
2189         case MONO_TYPE_I1:
2190         case MONO_TYPE_U1:
2191         case MONO_TYPE_I2:
2192         case MONO_TYPE_U2:
2193         case MONO_TYPE_I4:
2194         case MONO_TYPE_U4:
2195                 if (arg->type != STACK_I4 && arg->type != STACK_PTR)
2196                         return 1;
2197                 return 0;
2198         case MONO_TYPE_PTR:
2199                 /* STACK_MP is needed when setting pinned locals */
2200                 if (arg->type != STACK_I4 && arg->type != STACK_PTR && arg->type != STACK_MP)
2201                         return 1;
2202                 return 0;
2203         case MONO_TYPE_I:
2204         case MONO_TYPE_U:
2205         case MONO_TYPE_FNPTR:
2206                 /* 
2207                  * Some opcodes like ldloca returns 'transient pointers' which can be stored in
2208                  * in native int. (#688008).
2209                  */
2210                 if (arg->type != STACK_I4 && arg->type != STACK_PTR && arg->type != STACK_MP)
2211                         return 1;
2212                 return 0;
2213         case MONO_TYPE_CLASS:
2214         case MONO_TYPE_STRING:
2215         case MONO_TYPE_OBJECT:
2216         case MONO_TYPE_SZARRAY:
2217         case MONO_TYPE_ARRAY:    
2218                 if (arg->type != STACK_OBJ)
2219                         return 1;
2220                 /* FIXME: check type compatibility */
2221                 return 0;
2222         case MONO_TYPE_I8:
2223         case MONO_TYPE_U8:
2224                 if (arg->type != STACK_I8)
2225                         return 1;
2226                 return 0;
2227         case MONO_TYPE_R4:
2228                 if (arg->type != cfg->r4_stack_type)
2229                         return 1;
2230                 return 0;
2231         case MONO_TYPE_R8:
2232                 if (arg->type != STACK_R8)
2233                         return 1;
2234                 return 0;
2235         case MONO_TYPE_VALUETYPE:
2236                 if (arg->type != STACK_VTYPE)
2237                         return 1;
2238                 klass = mono_class_from_mono_type (simple_type);
2239                 if (klass != arg->klass)
2240                         return 1;
2241                 return 0;
2242         case MONO_TYPE_TYPEDBYREF:
2243                 if (arg->type != STACK_VTYPE)
2244                         return 1;
2245                 klass = mono_class_from_mono_type (simple_type);
2246                 if (klass != arg->klass)
2247                         return 1;
2248                 return 0;
2249         case MONO_TYPE_GENERICINST:
2250                 if (mono_type_generic_inst_is_valuetype (simple_type)) {
2251                         if (arg->type != STACK_VTYPE)
2252                                 return 1;
2253                         klass = mono_class_from_mono_type (simple_type);
2254                         /* The second cases is needed when doing partial sharing */
2255                         if (klass != arg->klass && mono_class_from_mono_type (target) != arg->klass)
2256                                 return 1;
2257                         return 0;
2258                 } else {
2259                         if (arg->type != STACK_OBJ)
2260                                 return 1;
2261                         /* FIXME: check type compatibility */
2262                         return 0;
2263                 }
2264         case MONO_TYPE_VAR:
2265         case MONO_TYPE_MVAR:
2266                 g_assert (cfg->gshared);
2267                 if (mini_type_var_is_vt (simple_type)) {
2268                         if (arg->type != STACK_VTYPE)
2269                                 return 1;
2270                 } else {
2271                         if (arg->type != STACK_OBJ)
2272                                 return 1;
2273                 }
2274                 return 0;
2275         default:
2276                 g_error ("unknown type 0x%02x in target_type_is_incompatible", simple_type->type);
2277         }
2278         return 1;
2279 }
2280
2281 /*
2282  * Prepare arguments for passing to a function call.
2283  * Return a non-zero value if the arguments can't be passed to the given
2284  * signature.
2285  * The type checks are not yet complete and some conversions may need
2286  * casts on 32 or 64 bit architectures.
2287  *
2288  * FIXME: implement this using target_type_is_incompatible ()
2289  */
2290 static int
2291 check_call_signature (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **args)
2292 {
2293         MonoType *simple_type;
2294         int i;
2295
2296         if (sig->hasthis) {
2297                 if (args [0]->type != STACK_OBJ && args [0]->type != STACK_MP && args [0]->type != STACK_PTR)
2298                         return 1;
2299                 args++;
2300         }
2301         for (i = 0; i < sig->param_count; ++i) {
2302                 if (sig->params [i]->byref) {
2303                         if (args [i]->type != STACK_MP && args [i]->type != STACK_PTR)
2304                                 return 1;
2305                         continue;
2306                 }
2307                 simple_type = mini_get_underlying_type (sig->params [i]);
2308 handle_enum:
2309                 switch (simple_type->type) {
2310                 case MONO_TYPE_VOID:
2311                         return 1;
2312                         continue;
2313                 case MONO_TYPE_I1:
2314                 case MONO_TYPE_U1:
2315                 case MONO_TYPE_I2:
2316                 case MONO_TYPE_U2:
2317                 case MONO_TYPE_I4:
2318                 case MONO_TYPE_U4:
2319                         if (args [i]->type != STACK_I4 && args [i]->type != STACK_PTR)
2320                                 return 1;
2321                         continue;
2322                 case MONO_TYPE_I:
2323                 case MONO_TYPE_U:
2324                 case MONO_TYPE_PTR:
2325                 case MONO_TYPE_FNPTR:
2326                         if (args [i]->type != STACK_I4 && args [i]->type != STACK_PTR && args [i]->type != STACK_MP && args [i]->type != STACK_OBJ)
2327                                 return 1;
2328                         continue;
2329                 case MONO_TYPE_CLASS:
2330                 case MONO_TYPE_STRING:
2331                 case MONO_TYPE_OBJECT:
2332                 case MONO_TYPE_SZARRAY:
2333                 case MONO_TYPE_ARRAY:    
2334                         if (args [i]->type != STACK_OBJ)
2335                                 return 1;
2336                         continue;
2337                 case MONO_TYPE_I8:
2338                 case MONO_TYPE_U8:
2339                         if (args [i]->type != STACK_I8)
2340                                 return 1;
2341                         continue;
2342                 case MONO_TYPE_R4:
2343                         if (args [i]->type != cfg->r4_stack_type)
2344                                 return 1;
2345                         continue;
2346                 case MONO_TYPE_R8:
2347                         if (args [i]->type != STACK_R8)
2348                                 return 1;
2349                         continue;
2350                 case MONO_TYPE_VALUETYPE:
2351                         if (simple_type->data.klass->enumtype) {
2352                                 simple_type = mono_class_enum_basetype (simple_type->data.klass);
2353                                 goto handle_enum;
2354                         }
2355                         if (args [i]->type != STACK_VTYPE)
2356                                 return 1;
2357                         continue;
2358                 case MONO_TYPE_TYPEDBYREF:
2359                         if (args [i]->type != STACK_VTYPE)
2360                                 return 1;
2361                         continue;
2362                 case MONO_TYPE_GENERICINST:
2363                         simple_type = &simple_type->data.generic_class->container_class->byval_arg;
2364                         goto handle_enum;
2365                 case MONO_TYPE_VAR:
2366                 case MONO_TYPE_MVAR:
2367                         /* gsharedvt */
2368                         if (args [i]->type != STACK_VTYPE)
2369                                 return 1;
2370                         continue;
2371                 default:
2372                         g_error ("unknown type 0x%02x in check_call_signature",
2373                                  simple_type->type);
2374                 }
2375         }
2376         return 0;
2377 }
2378
2379 static int
2380 callvirt_to_call (int opcode)
2381 {
2382         switch (opcode) {
2383         case OP_CALL_MEMBASE:
2384                 return OP_CALL;
2385         case OP_VOIDCALL_MEMBASE:
2386                 return OP_VOIDCALL;
2387         case OP_FCALL_MEMBASE:
2388                 return OP_FCALL;
2389         case OP_RCALL_MEMBASE:
2390                 return OP_RCALL;
2391         case OP_VCALL_MEMBASE:
2392                 return OP_VCALL;
2393         case OP_LCALL_MEMBASE:
2394                 return OP_LCALL;
2395         default:
2396                 g_assert_not_reached ();
2397         }
2398
2399         return -1;
2400 }
2401
2402 static int
2403 callvirt_to_call_reg (int opcode)
2404 {
2405         switch (opcode) {
2406         case OP_CALL_MEMBASE:
2407                 return OP_CALL_REG;
2408         case OP_VOIDCALL_MEMBASE:
2409                 return OP_VOIDCALL_REG;
2410         case OP_FCALL_MEMBASE:
2411                 return OP_FCALL_REG;
2412         case OP_RCALL_MEMBASE:
2413                 return OP_RCALL_REG;
2414         case OP_VCALL_MEMBASE:
2415                 return OP_VCALL_REG;
2416         case OP_LCALL_MEMBASE:
2417                 return OP_LCALL_REG;
2418         default:
2419                 g_assert_not_reached ();
2420         }
2421
2422         return -1;
2423 }
2424
2425 /* Either METHOD or IMT_ARG needs to be set */
2426 static void
2427 emit_imt_argument (MonoCompile *cfg, MonoCallInst *call, MonoMethod *method, MonoInst *imt_arg)
2428 {
2429         int method_reg;
2430
2431         if (COMPILE_LLVM (cfg)) {
2432                 method_reg = alloc_preg (cfg);
2433
2434                 if (imt_arg) {
2435                         MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, method_reg, imt_arg->dreg);
2436                 } else if (cfg->compile_aot) {
2437                         MONO_EMIT_NEW_AOTCONST (cfg, method_reg, method, MONO_PATCH_INFO_METHODCONST);
2438                 } else {
2439                         MonoInst *ins;
2440                         MONO_INST_NEW (cfg, ins, OP_PCONST);
2441                         ins->inst_p0 = method;
2442                         ins->dreg = method_reg;
2443                         MONO_ADD_INS (cfg->cbb, ins);
2444                 }
2445
2446 #ifdef ENABLE_LLVM
2447                 call->imt_arg_reg = method_reg;
2448 #endif
2449                 mono_call_inst_add_outarg_reg (cfg, call, method_reg, MONO_ARCH_IMT_REG, FALSE);
2450                 return;
2451         }
2452
2453         method_reg = alloc_preg (cfg);
2454
2455         if (imt_arg) {
2456                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, method_reg, imt_arg->dreg);
2457         } else if (cfg->compile_aot) {
2458                 MONO_EMIT_NEW_AOTCONST (cfg, method_reg, method, MONO_PATCH_INFO_METHODCONST);
2459         } else {
2460                 MonoInst *ins;
2461                 MONO_INST_NEW (cfg, ins, OP_PCONST);
2462                 ins->inst_p0 = method;
2463                 ins->dreg = method_reg;
2464                 MONO_ADD_INS (cfg->cbb, ins);
2465         }
2466
2467         mono_call_inst_add_outarg_reg (cfg, call, method_reg, MONO_ARCH_IMT_REG, FALSE);
2468 }
2469
2470 static MonoJumpInfo *
2471 mono_patch_info_new (MonoMemPool *mp, int ip, MonoJumpInfoType type, gconstpointer target)
2472 {
2473         MonoJumpInfo *ji = mono_mempool_alloc (mp, sizeof (MonoJumpInfo));
2474
2475         ji->ip.i = ip;
2476         ji->type = type;
2477         ji->data.target = target;
2478
2479         return ji;
2480 }
2481
2482 static int
2483 mini_class_check_context_used (MonoCompile *cfg, MonoClass *klass)
2484 {
2485         if (cfg->gshared)
2486                 return mono_class_check_context_used (klass);
2487         else
2488                 return 0;
2489 }
2490
2491 static int
2492 mini_method_check_context_used (MonoCompile *cfg, MonoMethod *method)
2493 {
2494         if (cfg->gshared)
2495                 return mono_method_check_context_used (method);
2496         else
2497                 return 0;
2498 }
2499
2500 /*
2501  * check_method_sharing:
2502  *
2503  *   Check whenever the vtable or an mrgctx needs to be passed when calling CMETHOD.
2504  */
2505 static void
2506 check_method_sharing (MonoCompile *cfg, MonoMethod *cmethod, gboolean *out_pass_vtable, gboolean *out_pass_mrgctx)
2507 {
2508         gboolean pass_vtable = FALSE;
2509         gboolean pass_mrgctx = FALSE;
2510
2511         if (((cmethod->flags & METHOD_ATTRIBUTE_STATIC) || cmethod->klass->valuetype) &&
2512                 (cmethod->klass->generic_class || cmethod->klass->generic_container)) {
2513                 gboolean sharable = FALSE;
2514
2515                 if (mono_method_is_generic_sharable_full (cmethod, TRUE, TRUE, TRUE))
2516                         sharable = TRUE;
2517
2518                 /*
2519                  * Pass vtable iff target method might
2520                  * be shared, which means that sharing
2521                  * is enabled for its class and its
2522                  * context is sharable (and it's not a
2523                  * generic method).
2524                  */
2525                 if (sharable && !(mini_method_get_context (cmethod) && mini_method_get_context (cmethod)->method_inst))
2526                         pass_vtable = TRUE;
2527         }
2528
2529         if (mini_method_get_context (cmethod) &&
2530                 mini_method_get_context (cmethod)->method_inst) {
2531                 g_assert (!pass_vtable);
2532
2533                 if (mono_method_is_generic_sharable_full (cmethod, TRUE, TRUE, TRUE)) {
2534                         pass_mrgctx = TRUE;
2535                 } else {
2536                         if (cfg->gsharedvt && mini_is_gsharedvt_signature (mono_method_signature (cmethod)))
2537                                 pass_mrgctx = TRUE;
2538                 }
2539         }
2540
2541         if (out_pass_vtable)
2542                 *out_pass_vtable = pass_vtable;
2543         if (out_pass_mrgctx)
2544                 *out_pass_mrgctx = pass_mrgctx;
2545 }
2546
2547 inline static MonoCallInst *
2548 mono_emit_call_args (MonoCompile *cfg, MonoMethodSignature *sig, 
2549                                          MonoInst **args, int calli, int virtual, int tail, int rgctx, int unbox_trampoline)
2550 {
2551         MonoType *sig_ret;
2552         MonoCallInst *call;
2553 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
2554         int i;
2555 #endif
2556
2557         if (cfg->llvm_only)
2558                 tail = FALSE;
2559
2560         if (tail) {
2561                 emit_instrumentation_call (cfg, mono_profiler_method_leave);
2562
2563                 MONO_INST_NEW_CALL (cfg, call, OP_TAILCALL);
2564         } else
2565                 MONO_INST_NEW_CALL (cfg, call, ret_type_to_call_opcode (cfg, sig->ret, calli, virtual));
2566
2567         call->args = args;
2568         call->signature = sig;
2569         call->rgctx_reg = rgctx;
2570         sig_ret = mini_get_underlying_type (sig->ret);
2571
2572         type_to_eval_stack_type ((cfg), sig_ret, &call->inst);
2573
2574         if (tail) {
2575                 if (mini_type_is_vtype (sig_ret)) {
2576                         call->vret_var = cfg->vret_addr;
2577                         //g_assert_not_reached ();
2578                 }
2579         } else if (mini_type_is_vtype (sig_ret)) {
2580                 MonoInst *temp = mono_compile_create_var (cfg, sig_ret, OP_LOCAL);
2581                 MonoInst *loada;
2582
2583                 temp->backend.is_pinvoke = sig->pinvoke;
2584
2585                 /*
2586                  * We use a new opcode OP_OUTARG_VTRETADDR instead of LDADDR for emitting the
2587                  * address of return value to increase optimization opportunities.
2588                  * Before vtype decomposition, the dreg of the call ins itself represents the
2589                  * fact the call modifies the return value. After decomposition, the call will
2590                  * be transformed into one of the OP_VOIDCALL opcodes, and the VTRETADDR opcode
2591                  * will be transformed into an LDADDR.
2592                  */
2593                 MONO_INST_NEW (cfg, loada, OP_OUTARG_VTRETADDR);
2594                 loada->dreg = alloc_preg (cfg);
2595                 loada->inst_p0 = temp;
2596                 /* We reference the call too since call->dreg could change during optimization */
2597                 loada->inst_p1 = call;
2598                 MONO_ADD_INS (cfg->cbb, loada);
2599
2600                 call->inst.dreg = temp->dreg;
2601
2602                 call->vret_var = loada;
2603         } else if (!MONO_TYPE_IS_VOID (sig_ret))
2604                 call->inst.dreg = alloc_dreg (cfg, call->inst.type);
2605
2606 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
2607         if (COMPILE_SOFT_FLOAT (cfg)) {
2608                 /* 
2609                  * If the call has a float argument, we would need to do an r8->r4 conversion using 
2610                  * an icall, but that cannot be done during the call sequence since it would clobber
2611                  * the call registers + the stack. So we do it before emitting the call.
2612                  */
2613                 for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
2614                         MonoType *t;
2615                         MonoInst *in = call->args [i];
2616
2617                         if (i >= sig->hasthis)
2618                                 t = sig->params [i - sig->hasthis];
2619                         else
2620                                 t = &mono_defaults.int_class->byval_arg;
2621                         t = mono_type_get_underlying_type (t);
2622
2623                         if (!t->byref && t->type == MONO_TYPE_R4) {
2624                                 MonoInst *iargs [1];
2625                                 MonoInst *conv;
2626
2627                                 iargs [0] = in;
2628                                 conv = mono_emit_jit_icall (cfg, mono_fload_r4_arg, iargs);
2629
2630                                 /* The result will be in an int vreg */
2631                                 call->args [i] = conv;
2632                         }
2633                 }
2634         }
2635 #endif
2636
2637         call->need_unbox_trampoline = unbox_trampoline;
2638
2639 #ifdef ENABLE_LLVM
2640         if (COMPILE_LLVM (cfg))
2641                 mono_llvm_emit_call (cfg, call);
2642         else
2643                 mono_arch_emit_call (cfg, call);
2644 #else
2645         mono_arch_emit_call (cfg, call);
2646 #endif
2647
2648         cfg->param_area = MAX (cfg->param_area, call->stack_usage);
2649         cfg->flags |= MONO_CFG_HAS_CALLS;
2650         
2651         return call;
2652 }
2653
2654 static void
2655 set_rgctx_arg (MonoCompile *cfg, MonoCallInst *call, int rgctx_reg, MonoInst *rgctx_arg)
2656 {
2657         mono_call_inst_add_outarg_reg (cfg, call, rgctx_reg, MONO_ARCH_RGCTX_REG, FALSE);
2658         cfg->uses_rgctx_reg = TRUE;
2659         call->rgctx_reg = TRUE;
2660 #ifdef ENABLE_LLVM
2661         call->rgctx_arg_reg = rgctx_reg;
2662 #endif
2663 }       
2664
2665 inline static MonoInst*
2666 mono_emit_calli (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **args, MonoInst *addr, MonoInst *imt_arg, MonoInst *rgctx_arg)
2667 {
2668         MonoCallInst *call;
2669         MonoInst *ins;
2670         int rgctx_reg = -1;
2671         gboolean check_sp = FALSE;
2672
2673         if (cfg->check_pinvoke_callconv && cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
2674                 WrapperInfo *info = mono_marshal_get_wrapper_info (cfg->method);
2675
2676                 if (info && info->subtype == WRAPPER_SUBTYPE_PINVOKE)
2677                         check_sp = TRUE;
2678         }
2679
2680         if (rgctx_arg) {
2681                 rgctx_reg = mono_alloc_preg (cfg);
2682                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, rgctx_reg, rgctx_arg->dreg);
2683         }
2684
2685         if (check_sp) {
2686                 if (!cfg->stack_inbalance_var)
2687                         cfg->stack_inbalance_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
2688
2689                 MONO_INST_NEW (cfg, ins, OP_GET_SP);
2690                 ins->dreg = cfg->stack_inbalance_var->dreg;
2691                 MONO_ADD_INS (cfg->cbb, ins);
2692         }
2693
2694         call = mono_emit_call_args (cfg, sig, args, TRUE, FALSE, FALSE, rgctx_arg ? TRUE : FALSE, FALSE);
2695
2696         call->inst.sreg1 = addr->dreg;
2697
2698         if (imt_arg)
2699                 emit_imt_argument (cfg, call, NULL, imt_arg);
2700
2701         MONO_ADD_INS (cfg->cbb, (MonoInst*)call);
2702
2703         if (check_sp) {
2704                 int sp_reg;
2705
2706                 sp_reg = mono_alloc_preg (cfg);
2707
2708                 MONO_INST_NEW (cfg, ins, OP_GET_SP);
2709                 ins->dreg = sp_reg;
2710                 MONO_ADD_INS (cfg->cbb, ins);
2711
2712                 /* Restore the stack so we don't crash when throwing the exception */
2713                 MONO_INST_NEW (cfg, ins, OP_SET_SP);
2714                 ins->sreg1 = cfg->stack_inbalance_var->dreg;
2715                 MONO_ADD_INS (cfg->cbb, ins);
2716
2717                 MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, cfg->stack_inbalance_var->dreg, sp_reg);
2718                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "ExecutionEngineException");
2719         }
2720
2721         if (rgctx_arg)
2722                 set_rgctx_arg (cfg, call, rgctx_reg, rgctx_arg);
2723
2724         return (MonoInst*)call;
2725 }
2726
2727 static MonoInst*
2728 emit_get_gsharedvt_info_klass (MonoCompile *cfg, MonoClass *klass, MonoRgctxInfoType rgctx_type);
2729
2730 static MonoInst*
2731 emit_get_rgctx_method (MonoCompile *cfg, int context_used, MonoMethod *cmethod, MonoRgctxInfoType rgctx_type);
2732 static MonoInst*
2733 emit_get_rgctx_klass (MonoCompile *cfg, int context_used, MonoClass *klass, MonoRgctxInfoType rgctx_type);
2734
2735 static MonoInst*
2736 mono_emit_method_call_full (MonoCompile *cfg, MonoMethod *method, MonoMethodSignature *sig, gboolean tail,
2737                                                         MonoInst **args, MonoInst *this_ins, MonoInst *imt_arg, MonoInst *rgctx_arg)
2738 {
2739 #ifndef DISABLE_REMOTING
2740         gboolean might_be_remote = FALSE;
2741 #endif
2742         gboolean virtual = this_ins != NULL;
2743         gboolean enable_for_aot = TRUE;
2744         int context_used;
2745         MonoCallInst *call;
2746         MonoInst *call_target = NULL;
2747         int rgctx_reg = 0;
2748         gboolean need_unbox_trampoline;
2749
2750         if (!sig)
2751                 sig = mono_method_signature (method);
2752
2753         if (cfg->llvm_only && (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
2754                 MonoInst *icall_args [16];
2755                 MonoInst *ins;
2756
2757                 // FIXME: Optimize this
2758
2759                 guint32 imt_slot = mono_method_get_imt_slot (method);
2760
2761                 icall_args [0] = this_ins;
2762                 EMIT_NEW_ICONST (cfg, icall_args [1], imt_slot);
2763                 if (imt_arg) {
2764                         icall_args [2] = imt_arg;
2765                 } else {
2766                         EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_METHODCONST, method);
2767                         icall_args [2] = ins;
2768                 }
2769                 EMIT_NEW_PCONST (cfg, icall_args [3], NULL);
2770
2771                 call_target = mono_emit_jit_icall (cfg, mono_resolve_iface_call, icall_args);
2772         }
2773
2774         if (rgctx_arg) {
2775                 rgctx_reg = mono_alloc_preg (cfg);
2776                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, rgctx_reg, rgctx_arg->dreg);
2777         }
2778
2779         if (method->string_ctor) {
2780                 /* Create the real signature */
2781                 /* FIXME: Cache these */
2782                 MonoMethodSignature *ctor_sig = mono_metadata_signature_dup_mempool (cfg->mempool, sig);
2783                 ctor_sig->ret = &mono_defaults.string_class->byval_arg;
2784
2785                 sig = ctor_sig;
2786         }
2787
2788         context_used = mini_method_check_context_used (cfg, method);
2789
2790 #ifndef DISABLE_REMOTING
2791         might_be_remote = this_ins && sig->hasthis &&
2792                 (mono_class_is_marshalbyref (method->klass) || method->klass == mono_defaults.object_class) &&
2793                 !(method->flags & METHOD_ATTRIBUTE_VIRTUAL) && (!MONO_CHECK_THIS (this_ins) || context_used);
2794
2795         if (might_be_remote && context_used) {
2796                 MonoInst *addr;
2797
2798                 g_assert (cfg->gshared);
2799
2800                 addr = emit_get_rgctx_method (cfg, context_used, method, MONO_RGCTX_INFO_REMOTING_INVOKE_WITH_CHECK);
2801
2802                 return mono_emit_calli (cfg, sig, args, addr, NULL, NULL);
2803         }
2804 #endif
2805
2806         if (cfg->llvm_only && !call_target && virtual && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
2807                 // FIXME: Vcall optimizations below
2808                 MonoInst *icall_args [16];
2809                 MonoInst *ins;
2810
2811                 if (sig->generic_param_count) {
2812                         /*
2813                          * Generic virtual call, pass the concrete method as the imt argument.
2814                          */
2815                         imt_arg = emit_get_rgctx_method (cfg, context_used,
2816                                                                                          method, MONO_RGCTX_INFO_METHOD);
2817                 }
2818
2819                 // FIXME: Optimize this
2820
2821                 int slot = mono_method_get_vtable_index (method);
2822
2823                 icall_args [0] = this_ins;
2824                 EMIT_NEW_ICONST (cfg, icall_args [1], slot);
2825                 if (imt_arg) {
2826                         icall_args [2] = imt_arg;
2827                 } else {
2828                         EMIT_NEW_PCONST (cfg, ins, NULL);
2829                         icall_args [2] = ins;
2830                 }
2831                 call_target = mono_emit_jit_icall (cfg, mono_resolve_vcall, icall_args);
2832         }
2833
2834         need_unbox_trampoline = method->klass == mono_defaults.object_class || (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE);
2835
2836         call = mono_emit_call_args (cfg, sig, args, FALSE, virtual, tail, rgctx_arg ? TRUE : FALSE, need_unbox_trampoline);
2837
2838 #ifndef DISABLE_REMOTING
2839         if (might_be_remote)
2840                 call->method = mono_marshal_get_remoting_invoke_with_check (method);
2841         else
2842 #endif
2843                 call->method = method;
2844         call->inst.flags |= MONO_INST_HAS_METHOD;
2845         call->inst.inst_left = this_ins;
2846         call->tail_call = tail;
2847
2848         if (virtual) {
2849                 int vtable_reg, slot_reg, this_reg;
2850                 int offset;
2851
2852                 this_reg = this_ins->dreg;
2853
2854                 if (!cfg->llvm_only && (method->klass->parent == mono_defaults.multicastdelegate_class) && !strcmp (method->name, "Invoke")) {
2855                         MonoInst *dummy_use;
2856
2857                         MONO_EMIT_NULL_CHECK (cfg, this_reg);
2858
2859                         /* Make a call to delegate->invoke_impl */
2860                         call->inst.inst_basereg = this_reg;
2861                         call->inst.inst_offset = MONO_STRUCT_OFFSET (MonoDelegate, invoke_impl);
2862                         MONO_ADD_INS (cfg->cbb, (MonoInst*)call);
2863
2864                         /* We must emit a dummy use here because the delegate trampoline will
2865                         replace the 'this' argument with the delegate target making this activation
2866                         no longer a root for the delegate.
2867                         This is an issue for delegates that target collectible code such as dynamic
2868                         methods of GC'able assemblies.
2869
2870                         For a test case look into #667921.
2871
2872                         FIXME: a dummy use is not the best way to do it as the local register allocator
2873                         will put it on a caller save register and spil it around the call. 
2874                         Ideally, we would either put it on a callee save register or only do the store part.  
2875                          */
2876                         EMIT_NEW_DUMMY_USE (cfg, dummy_use, args [0]);
2877
2878                         return (MonoInst*)call;
2879                 }
2880
2881                 if ((!cfg->compile_aot || enable_for_aot) && 
2882                         (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) || 
2883                          (MONO_METHOD_IS_FINAL (method) &&
2884                           method->wrapper_type != MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)) &&
2885                         !(mono_class_is_marshalbyref (method->klass) && context_used)) {
2886                         /* 
2887                          * the method is not virtual, we just need to ensure this is not null
2888                          * and then we can call the method directly.
2889                          */
2890 #ifndef DISABLE_REMOTING
2891                         if (mono_class_is_marshalbyref (method->klass) || method->klass == mono_defaults.object_class) {
2892                                 /* 
2893                                  * The check above ensures method is not gshared, this is needed since
2894                                  * gshared methods can't have wrappers.
2895                                  */
2896                                 method = call->method = mono_marshal_get_remoting_invoke_with_check (method);
2897                         }
2898 #endif
2899
2900                         if (!method->string_ctor)
2901                                 MONO_EMIT_NEW_CHECK_THIS (cfg, this_reg);
2902
2903                         call->inst.opcode = callvirt_to_call (call->inst.opcode);
2904                 } else if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) && MONO_METHOD_IS_FINAL (method)) {
2905                         /*
2906                          * the method is virtual, but we can statically dispatch since either
2907                          * it's class or the method itself are sealed.
2908                          * But first we need to ensure it's not a null reference.
2909                          */
2910                         MONO_EMIT_NEW_CHECK_THIS (cfg, this_reg);
2911
2912                         call->inst.opcode = callvirt_to_call (call->inst.opcode);
2913                 } else if (call_target) {
2914                         vtable_reg = alloc_preg (cfg);
2915                         MONO_EMIT_NEW_LOAD_MEMBASE_FAULT (cfg, vtable_reg, this_reg, MONO_STRUCT_OFFSET (MonoObject, vtable));
2916
2917                         call->inst.opcode = callvirt_to_call_reg (call->inst.opcode);
2918                         call->inst.sreg1 = call_target->dreg;
2919                         call->inst.flags &= !MONO_INST_HAS_METHOD;
2920                 } else {
2921                         vtable_reg = alloc_preg (cfg);
2922                         MONO_EMIT_NEW_LOAD_MEMBASE_FAULT (cfg, vtable_reg, this_reg, MONO_STRUCT_OFFSET (MonoObject, vtable));
2923                         if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
2924                                 guint32 imt_slot = mono_method_get_imt_slot (method);
2925                                 emit_imt_argument (cfg, call, call->method, imt_arg);
2926                                 slot_reg = vtable_reg;
2927                                 offset = ((gint32)imt_slot - MONO_IMT_SIZE) * SIZEOF_VOID_P;
2928                         } else {
2929                                 slot_reg = vtable_reg;
2930                                 offset = MONO_STRUCT_OFFSET (MonoVTable, vtable) +
2931                                         ((mono_method_get_vtable_index (method)) * (SIZEOF_VOID_P));
2932                                 if (imt_arg) {
2933                                         g_assert (mono_method_signature (method)->generic_param_count);
2934                                         emit_imt_argument (cfg, call, call->method, imt_arg);
2935                                 }
2936                         }
2937
2938                         call->inst.sreg1 = slot_reg;
2939                         call->inst.inst_offset = offset;
2940                         call->is_virtual = TRUE;
2941                 }
2942         }
2943
2944         MONO_ADD_INS (cfg->cbb, (MonoInst*)call);
2945
2946         if (rgctx_arg)
2947                 set_rgctx_arg (cfg, call, rgctx_reg, rgctx_arg);
2948
2949         return (MonoInst*)call;
2950 }
2951
2952 MonoInst*
2953 mono_emit_method_call (MonoCompile *cfg, MonoMethod *method, MonoInst **args, MonoInst *this_ins)
2954 {
2955         return mono_emit_method_call_full (cfg, method, mono_method_signature (method), FALSE, args, this_ins, NULL, NULL);
2956 }
2957
2958 MonoInst*
2959 mono_emit_native_call (MonoCompile *cfg, gconstpointer func, MonoMethodSignature *sig,
2960                                            MonoInst **args)
2961 {
2962         MonoCallInst *call;
2963
2964         g_assert (sig);
2965
2966         call = mono_emit_call_args (cfg, sig, args, FALSE, FALSE, FALSE, FALSE, FALSE);
2967         call->fptr = func;
2968
2969         MONO_ADD_INS (cfg->cbb, (MonoInst*)call);
2970
2971         return (MonoInst*)call;
2972 }
2973
2974 MonoInst*
2975 mono_emit_jit_icall (MonoCompile *cfg, gconstpointer func, MonoInst **args)
2976 {
2977         MonoJitICallInfo *info = mono_find_jit_icall_by_addr (func);
2978
2979         g_assert (info);
2980
2981         return mono_emit_native_call (cfg, mono_icall_get_wrapper (info), info->sig, args);
2982 }
2983
2984 /*
2985  * mono_emit_abs_call:
2986  *
2987  *   Emit a call to the runtime function described by PATCH_TYPE and DATA.
2988  */
2989 inline static MonoInst*
2990 mono_emit_abs_call (MonoCompile *cfg, MonoJumpInfoType patch_type, gconstpointer data, 
2991                                         MonoMethodSignature *sig, MonoInst **args)
2992 {
2993         MonoJumpInfo *ji = mono_patch_info_new (cfg->mempool, 0, patch_type, data);
2994         MonoInst *ins;
2995
2996         /* 
2997          * We pass ji as the call address, the PATCH_INFO_ABS resolving code will
2998          * handle it.
2999          */
3000         if (cfg->abs_patches == NULL)
3001                 cfg->abs_patches = g_hash_table_new (NULL, NULL);
3002         g_hash_table_insert (cfg->abs_patches, ji, ji);
3003         ins = mono_emit_native_call (cfg, ji, sig, args);
3004         ((MonoCallInst*)ins)->fptr_is_patch = TRUE;
3005         return ins;
3006 }
3007
3008 static gboolean
3009 direct_icalls_enabled (MonoCompile *cfg)
3010 {
3011         /* LLVM on amd64 can't handle calls to non-32 bit addresses */
3012 #ifdef TARGET_AMD64
3013         if (cfg->compile_llvm)
3014                 return FALSE;
3015 #endif
3016         if (cfg->gen_sdb_seq_points || cfg->disable_direct_icalls)
3017                 return FALSE;
3018         return TRUE;
3019 }
3020
3021 MonoInst*
3022 mono_emit_jit_icall_by_info (MonoCompile *cfg, MonoJitICallInfo *info, MonoInst **args)
3023 {
3024         /*
3025          * Call the jit icall without a wrapper if possible.
3026          * The wrapper is needed for the following reasons:
3027          * - to handle exceptions thrown using mono_raise_exceptions () from the
3028          *   icall function. The EH code needs the lmf frame pushed by the
3029          *   wrapper to be able to unwind back to managed code.
3030          * - to be able to do stack walks for asynchronously suspended
3031          *   threads when debugging.
3032          */
3033         if (info->no_raise && direct_icalls_enabled (cfg)) {
3034                 char *name;
3035                 int costs;
3036
3037                 if (!info->wrapper_method) {
3038                         name = g_strdup_printf ("__icall_wrapper_%s", info->name);
3039                         info->wrapper_method = mono_marshal_get_icall_wrapper (info->sig, name, info->func, TRUE);
3040                         g_free (name);
3041                         mono_memory_barrier ();
3042                 }
3043
3044                 /*
3045                  * Inline the wrapper method, which is basically a call to the C icall, and
3046                  * an exception check.
3047                  */
3048                 costs = inline_method (cfg, info->wrapper_method, NULL,
3049                                                            args, NULL, cfg->real_offset, TRUE);
3050                 g_assert (costs > 0);
3051                 g_assert (!MONO_TYPE_IS_VOID (info->sig->ret));
3052
3053                 return args [0];
3054         } else {
3055                 return mono_emit_native_call (cfg, mono_icall_get_wrapper (info), info->sig, args);
3056         }
3057 }
3058  
3059 static MonoInst*
3060 mono_emit_widen_call_res (MonoCompile *cfg, MonoInst *ins, MonoMethodSignature *fsig)
3061 {
3062         if (!MONO_TYPE_IS_VOID (fsig->ret)) {
3063                 if ((fsig->pinvoke || LLVM_ENABLED) && !fsig->ret->byref) {
3064                         int widen_op = -1;
3065
3066                         /* 
3067                          * Native code might return non register sized integers 
3068                          * without initializing the upper bits.
3069                          */
3070                         switch (mono_type_to_load_membase (cfg, fsig->ret)) {
3071                         case OP_LOADI1_MEMBASE:
3072                                 widen_op = OP_ICONV_TO_I1;
3073                                 break;
3074                         case OP_LOADU1_MEMBASE:
3075                                 widen_op = OP_ICONV_TO_U1;
3076                                 break;
3077                         case OP_LOADI2_MEMBASE:
3078                                 widen_op = OP_ICONV_TO_I2;
3079                                 break;
3080                         case OP_LOADU2_MEMBASE:
3081                                 widen_op = OP_ICONV_TO_U2;
3082                                 break;
3083                         default:
3084                                 break;
3085                         }
3086
3087                         if (widen_op != -1) {
3088                                 int dreg = alloc_preg (cfg);
3089                                 MonoInst *widen;
3090
3091                                 EMIT_NEW_UNALU (cfg, widen, widen_op, dreg, ins->dreg);
3092                                 widen->type = ins->type;
3093                                 ins = widen;
3094                         }
3095                 }
3096         }
3097
3098         return ins;
3099 }
3100
3101 static MonoMethod*
3102 get_memcpy_method (void)
3103 {
3104         static MonoMethod *memcpy_method = NULL;
3105         if (!memcpy_method) {
3106                 memcpy_method = mono_class_get_method_from_name (mono_defaults.string_class, "memcpy", 3);
3107                 if (!memcpy_method)
3108                         g_error ("Old corlib found. Install a new one");
3109         }
3110         return memcpy_method;
3111 }
3112
3113 static void
3114 create_write_barrier_bitmap (MonoCompile *cfg, MonoClass *klass, unsigned *wb_bitmap, int offset)
3115 {
3116         MonoClassField *field;
3117         gpointer iter = NULL;
3118
3119         while ((field = mono_class_get_fields (klass, &iter))) {
3120                 int foffset;
3121
3122                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
3123                         continue;
3124                 foffset = klass->valuetype ? field->offset - sizeof (MonoObject): field->offset;
3125                 if (mini_type_is_reference (mono_field_get_type (field))) {
3126                         g_assert ((foffset % SIZEOF_VOID_P) == 0);
3127                         *wb_bitmap |= 1 << ((offset + foffset) / SIZEOF_VOID_P);
3128                 } else {
3129                         MonoClass *field_class = mono_class_from_mono_type (field->type);
3130                         if (field_class->has_references)
3131                                 create_write_barrier_bitmap (cfg, field_class, wb_bitmap, offset + foffset);
3132                 }
3133         }
3134 }
3135
3136 static void
3137 emit_write_barrier (MonoCompile *cfg, MonoInst *ptr, MonoInst *value)
3138 {
3139         int card_table_shift_bits;
3140         gpointer card_table_mask;
3141         guint8 *card_table;
3142         MonoInst *dummy_use;
3143         int nursery_shift_bits;
3144         size_t nursery_size;
3145
3146         if (!cfg->gen_write_barriers)
3147                 return;
3148
3149         card_table = mono_gc_get_card_table (&card_table_shift_bits, &card_table_mask);
3150
3151         mono_gc_get_nursery (&nursery_shift_bits, &nursery_size);
3152
3153         if (cfg->backend->have_card_table_wb && !cfg->compile_aot && card_table && nursery_shift_bits > 0 && !COMPILE_LLVM (cfg)) {
3154                 MonoInst *wbarrier;
3155
3156                 MONO_INST_NEW (cfg, wbarrier, OP_CARD_TABLE_WBARRIER);
3157                 wbarrier->sreg1 = ptr->dreg;
3158                 wbarrier->sreg2 = value->dreg;
3159                 MONO_ADD_INS (cfg->cbb, wbarrier);
3160         } else if (card_table && !cfg->compile_aot && !mono_gc_card_table_nursery_check ()) {
3161                 int offset_reg = alloc_preg (cfg);
3162                 int card_reg  = alloc_preg (cfg);
3163                 MonoInst *ins;
3164
3165                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_UN_IMM, offset_reg, ptr->dreg, card_table_shift_bits);
3166                 if (card_table_mask)
3167                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_PAND_IMM, offset_reg, offset_reg, card_table_mask);
3168
3169                 /*We can't use PADD_IMM since the cardtable might end up in high addresses and amd64 doesn't support
3170                  * IMM's larger than 32bits.
3171                  */
3172                 if (cfg->compile_aot) {
3173                         MONO_EMIT_NEW_AOTCONST (cfg, card_reg, NULL, MONO_PATCH_INFO_GC_CARD_TABLE_ADDR);
3174                 } else {
3175                         MONO_INST_NEW (cfg, ins, OP_PCONST);
3176                         ins->inst_p0 = card_table;
3177                         ins->dreg = card_reg;
3178                         MONO_ADD_INS (cfg->cbb, ins);
3179                 }
3180
3181                 MONO_EMIT_NEW_BIALU (cfg, OP_PADD, offset_reg, offset_reg, card_reg);
3182                 MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STOREI1_MEMBASE_IMM, offset_reg, 0, 1);
3183         } else {
3184                 MonoMethod *write_barrier = mono_gc_get_write_barrier ();
3185                 mono_emit_method_call (cfg, write_barrier, &ptr, NULL);
3186         }
3187
3188         EMIT_NEW_DUMMY_USE (cfg, dummy_use, value);
3189 }
3190
3191 static gboolean
3192 mono_emit_wb_aware_memcpy (MonoCompile *cfg, MonoClass *klass, MonoInst *iargs[4], int size, int align)
3193 {
3194         int dest_ptr_reg, tmp_reg, destreg, srcreg, offset;
3195         unsigned need_wb = 0;
3196
3197         if (align == 0)
3198                 align = 4;
3199
3200         /*types with references can't have alignment smaller than sizeof(void*) */
3201         if (align < SIZEOF_VOID_P)
3202                 return FALSE;
3203
3204         /*This value cannot be bigger than 32 due to the way we calculate the required wb bitmap.*/
3205         if (size > 32 * SIZEOF_VOID_P)
3206                 return FALSE;
3207
3208         create_write_barrier_bitmap (cfg, klass, &need_wb, 0);
3209
3210         /* We don't unroll more than 5 stores to avoid code bloat. */
3211         if (size > 5 * SIZEOF_VOID_P) {
3212                 /*This is harmless and simplify mono_gc_wbarrier_value_copy_bitmap */
3213                 size += (SIZEOF_VOID_P - 1);
3214                 size &= ~(SIZEOF_VOID_P - 1);
3215
3216                 EMIT_NEW_ICONST (cfg, iargs [2], size);
3217                 EMIT_NEW_ICONST (cfg, iargs [3], need_wb);
3218                 mono_emit_jit_icall (cfg, mono_gc_wbarrier_value_copy_bitmap, iargs);
3219                 return TRUE;
3220         }
3221
3222         destreg = iargs [0]->dreg;
3223         srcreg = iargs [1]->dreg;
3224         offset = 0;
3225
3226         dest_ptr_reg = alloc_preg (cfg);
3227         tmp_reg = alloc_preg (cfg);
3228
3229         /*tmp = dreg*/
3230         EMIT_NEW_UNALU (cfg, iargs [0], OP_MOVE, dest_ptr_reg, destreg);
3231
3232         while (size >= SIZEOF_VOID_P) {
3233                 MonoInst *load_inst;
3234                 MONO_INST_NEW (cfg, load_inst, OP_LOAD_MEMBASE);
3235                 load_inst->dreg = tmp_reg;
3236                 load_inst->inst_basereg = srcreg;
3237                 load_inst->inst_offset = offset;
3238                 MONO_ADD_INS (cfg->cbb, load_inst);
3239
3240                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, dest_ptr_reg, 0, tmp_reg);
3241
3242                 if (need_wb & 0x1)
3243                         emit_write_barrier (cfg, iargs [0], load_inst);
3244
3245                 offset += SIZEOF_VOID_P;
3246                 size -= SIZEOF_VOID_P;
3247                 need_wb >>= 1;
3248
3249                 /*tmp += sizeof (void*)*/
3250                 if (size >= SIZEOF_VOID_P) {
3251                         NEW_BIALU_IMM (cfg, iargs [0], OP_PADD_IMM, dest_ptr_reg, dest_ptr_reg, SIZEOF_VOID_P);
3252                         MONO_ADD_INS (cfg->cbb, iargs [0]);
3253                 }
3254         }
3255
3256         /* Those cannot be references since size < sizeof (void*) */
3257         while (size >= 4) {
3258                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, tmp_reg, srcreg, offset);
3259                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, destreg, offset, tmp_reg);
3260                 offset += 4;
3261                 size -= 4;
3262         }
3263
3264         while (size >= 2) {
3265                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI2_MEMBASE, tmp_reg, srcreg, offset);
3266                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI2_MEMBASE_REG, destreg, offset, tmp_reg);
3267                 offset += 2;
3268                 size -= 2;
3269         }
3270
3271         while (size >= 1) {
3272                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI1_MEMBASE, tmp_reg, srcreg, offset);
3273                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, destreg, offset, tmp_reg);
3274                 offset += 1;
3275                 size -= 1;
3276         }
3277
3278         return TRUE;
3279 }
3280
3281 /*
3282  * Emit code to copy a valuetype of type @klass whose address is stored in
3283  * @src->dreg to memory whose address is stored at @dest->dreg.
3284  */
3285 void
3286 mini_emit_stobj (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *klass, gboolean native)
3287 {
3288         MonoInst *iargs [4];
3289         int n;
3290         guint32 align = 0;
3291         MonoMethod *memcpy_method;
3292         MonoInst *size_ins = NULL;
3293         MonoInst *memcpy_ins = NULL;
3294
3295         g_assert (klass);
3296         if (cfg->gshared)
3297                 klass = mono_class_from_mono_type (mini_get_underlying_type (&klass->byval_arg));
3298
3299         /*
3300          * This check breaks with spilled vars... need to handle it during verification anyway.
3301          * g_assert (klass && klass == src->klass && klass == dest->klass);
3302          */
3303
3304         if (mini_is_gsharedvt_klass (klass)) {
3305                 g_assert (!native);
3306                 size_ins = emit_get_gsharedvt_info_klass (cfg, klass, MONO_RGCTX_INFO_VALUE_SIZE);
3307                 memcpy_ins = emit_get_gsharedvt_info_klass (cfg, klass, MONO_RGCTX_INFO_MEMCPY);
3308         }
3309
3310         if (native)
3311                 n = mono_class_native_size (klass, &align);
3312         else
3313                 n = mono_class_value_size (klass, &align);
3314
3315         /* if native is true there should be no references in the struct */
3316         if (cfg->gen_write_barriers && (klass->has_references || size_ins) && !native) {
3317                 /* Avoid barriers when storing to the stack */
3318                 if (!((dest->opcode == OP_ADD_IMM && dest->sreg1 == cfg->frame_reg) ||
3319                           (dest->opcode == OP_LDADDR))) {
3320                         int context_used;
3321
3322                         iargs [0] = dest;
3323                         iargs [1] = src;
3324
3325                         context_used = mini_class_check_context_used (cfg, klass);
3326
3327                         /* It's ok to intrinsify under gsharing since shared code types are layout stable. */
3328                         if (!size_ins && (cfg->opt & MONO_OPT_INTRINS) && mono_emit_wb_aware_memcpy (cfg, klass, iargs, n, align)) {
3329                                 return;
3330                         } else if (context_used) {
3331                                 iargs [2] = emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS);
3332                         }  else {
3333                                 if (cfg->compile_aot) {
3334                                         EMIT_NEW_CLASSCONST (cfg, iargs [2], klass);
3335                                 } else {
3336                                         EMIT_NEW_PCONST (cfg, iargs [2], klass);
3337                                         mono_class_compute_gc_descriptor (klass);
3338                                 }
3339                         }
3340
3341                         if (size_ins)
3342                                 mono_emit_jit_icall (cfg, mono_gsharedvt_value_copy, iargs);
3343                         else
3344                                 mono_emit_jit_icall (cfg, mono_value_copy, iargs);
3345                         return;
3346                 }
3347         }
3348
3349         if (!size_ins && (cfg->opt & MONO_OPT_INTRINS) && n <= sizeof (gpointer) * 8) {
3350                 /* FIXME: Optimize the case when src/dest is OP_LDADDR */
3351                 mini_emit_memcpy (cfg, dest->dreg, 0, src->dreg, 0, n, align);
3352         } else {
3353                 iargs [0] = dest;
3354                 iargs [1] = src;
3355                 if (size_ins)
3356                         iargs [2] = size_ins;
3357                 else
3358                         EMIT_NEW_ICONST (cfg, iargs [2], n);
3359                 
3360                 memcpy_method = get_memcpy_method ();
3361                 if (memcpy_ins)
3362                         mono_emit_calli (cfg, mono_method_signature (memcpy_method), iargs, memcpy_ins, NULL, NULL);
3363                 else
3364                         mono_emit_method_call (cfg, memcpy_method, iargs, NULL);
3365         }
3366 }
3367
3368 static MonoMethod*
3369 get_memset_method (void)
3370 {
3371         static MonoMethod *memset_method = NULL;
3372         if (!memset_method) {
3373                 memset_method = mono_class_get_method_from_name (mono_defaults.string_class, "memset", 3);
3374                 if (!memset_method)
3375                         g_error ("Old corlib found. Install a new one");
3376         }
3377         return memset_method;
3378 }
3379
3380 void
3381 mini_emit_initobj (MonoCompile *cfg, MonoInst *dest, const guchar *ip, MonoClass *klass)
3382 {
3383         MonoInst *iargs [3];
3384         int n;
3385         guint32 align;
3386         MonoMethod *memset_method;
3387         MonoInst *size_ins = NULL;
3388         MonoInst *bzero_ins = NULL;
3389         static MonoMethod *bzero_method;
3390
3391         /* FIXME: Optimize this for the case when dest is an LDADDR */
3392         mono_class_init (klass);
3393         if (mini_is_gsharedvt_klass (klass)) {
3394                 size_ins = emit_get_gsharedvt_info_klass (cfg, klass, MONO_RGCTX_INFO_VALUE_SIZE);
3395                 bzero_ins = emit_get_gsharedvt_info_klass (cfg, klass, MONO_RGCTX_INFO_BZERO);
3396                 if (!bzero_method)
3397                         bzero_method = mono_class_get_method_from_name (mono_defaults.string_class, "bzero_aligned_1", 2);
3398                 g_assert (bzero_method);
3399                 iargs [0] = dest;
3400                 iargs [1] = size_ins;
3401                 mono_emit_calli (cfg, mono_method_signature (bzero_method), iargs, bzero_ins, NULL, NULL);
3402                 return;
3403         }
3404
3405         n = mono_class_value_size (klass, &align);
3406
3407         if (n <= sizeof (gpointer) * 8) {
3408                 mini_emit_memset (cfg, dest->dreg, 0, n, 0, align);
3409         }
3410         else {
3411                 memset_method = get_memset_method ();
3412                 iargs [0] = dest;
3413                 EMIT_NEW_ICONST (cfg, iargs [1], 0);
3414                 EMIT_NEW_ICONST (cfg, iargs [2], n);
3415                 mono_emit_method_call (cfg, memset_method, iargs, NULL);
3416         }
3417 }
3418
3419 /*
3420  * emit_get_rgctx:
3421  *
3422  *   Emit IR to return either the this pointer for instance method,
3423  * or the mrgctx for static methods.
3424  */
3425 static MonoInst*
3426 emit_get_rgctx (MonoCompile *cfg, MonoMethod *method, int context_used)
3427 {
3428         MonoInst *this_ins = NULL;
3429
3430         g_assert (cfg->gshared);
3431
3432         if (!(method->flags & METHOD_ATTRIBUTE_STATIC) &&
3433                         !(context_used & MONO_GENERIC_CONTEXT_USED_METHOD) &&
3434                         !method->klass->valuetype)
3435                 EMIT_NEW_ARGLOAD (cfg, this_ins, 0);
3436
3437         if (context_used & MONO_GENERIC_CONTEXT_USED_METHOD) {
3438                 MonoInst *mrgctx_loc, *mrgctx_var;
3439
3440                 g_assert (!this_ins);
3441                 g_assert (method->is_inflated && mono_method_get_context (method)->method_inst);
3442
3443                 mrgctx_loc = mono_get_vtable_var (cfg);
3444                 EMIT_NEW_TEMPLOAD (cfg, mrgctx_var, mrgctx_loc->inst_c0);
3445
3446                 return mrgctx_var;
3447         } else if (method->flags & METHOD_ATTRIBUTE_STATIC || method->klass->valuetype) {
3448                 MonoInst *vtable_loc, *vtable_var;
3449
3450                 g_assert (!this_ins);
3451
3452                 vtable_loc = mono_get_vtable_var (cfg);
3453                 EMIT_NEW_TEMPLOAD (cfg, vtable_var, vtable_loc->inst_c0);
3454
3455                 if (method->is_inflated && mono_method_get_context (method)->method_inst) {
3456                         MonoInst *mrgctx_var = vtable_var;
3457                         int vtable_reg;
3458
3459                         vtable_reg = alloc_preg (cfg);
3460                         EMIT_NEW_LOAD_MEMBASE (cfg, vtable_var, OP_LOAD_MEMBASE, vtable_reg, mrgctx_var->dreg, MONO_STRUCT_OFFSET (MonoMethodRuntimeGenericContext, class_vtable));
3461                         vtable_var->type = STACK_PTR;
3462                 }
3463
3464                 return vtable_var;
3465         } else {
3466                 MonoInst *ins;
3467                 int vtable_reg;
3468         
3469                 vtable_reg = alloc_preg (cfg);
3470                 EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, vtable_reg, this_ins->dreg, MONO_STRUCT_OFFSET (MonoObject, vtable));
3471                 return ins;
3472         }
3473 }
3474
3475 static MonoJumpInfoRgctxEntry *
3476 mono_patch_info_rgctx_entry_new (MonoMemPool *mp, MonoMethod *method, gboolean in_mrgctx, MonoJumpInfoType patch_type, gconstpointer patch_data, MonoRgctxInfoType info_type)
3477 {
3478         MonoJumpInfoRgctxEntry *res = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoRgctxEntry));
3479         res->method = method;
3480         res->in_mrgctx = in_mrgctx;
3481         res->data = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfo));
3482         res->data->type = patch_type;
3483         res->data->data.target = patch_data;
3484         res->info_type = info_type;
3485
3486         return res;
3487 }
3488
3489 static inline MonoInst*
3490 emit_rgctx_fetch_inline (MonoCompile *cfg, MonoInst *rgctx, MonoJumpInfoRgctxEntry *entry)
3491 {
3492         MonoInst *args [16];
3493         MonoInst *call;
3494
3495         // FIXME: No fastpath since the slot is not a compile time constant
3496         args [0] = rgctx;
3497         EMIT_NEW_AOTCONST (cfg, args [1], MONO_PATCH_INFO_RGCTX_SLOT_INDEX, entry);
3498         if (entry->in_mrgctx)
3499                 call = mono_emit_jit_icall (cfg, mono_fill_method_rgctx, args);
3500         else
3501                 call = mono_emit_jit_icall (cfg, mono_fill_class_rgctx, args);
3502         return call;
3503 #if 0
3504         /*
3505          * FIXME: This can be called during decompose, which is a problem since it creates
3506          * new bblocks.
3507          * Also, the fastpath doesn't work since the slot number is dynamically allocated.
3508          */
3509         int i, slot, depth, index, rgctx_reg, val_reg, res_reg;
3510         gboolean mrgctx;
3511         MonoBasicBlock *is_null_bb, *end_bb;
3512         MonoInst *res, *ins, *call;
3513         MonoInst *args[16];
3514
3515         slot = mini_get_rgctx_entry_slot (entry);
3516
3517         mrgctx = MONO_RGCTX_SLOT_IS_MRGCTX (slot);
3518         index = MONO_RGCTX_SLOT_INDEX (slot);
3519         if (mrgctx)
3520                 index += MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT / sizeof (gpointer);
3521         for (depth = 0; ; ++depth) {
3522                 int size = mono_class_rgctx_get_array_size (depth, mrgctx);
3523
3524                 if (index < size - 1)
3525                         break;
3526                 index -= size - 1;
3527         }
3528
3529         NEW_BBLOCK (cfg, end_bb);
3530         NEW_BBLOCK (cfg, is_null_bb);
3531
3532         if (mrgctx) {
3533                 rgctx_reg = rgctx->dreg;
3534         } else {
3535                 rgctx_reg = alloc_preg (cfg);
3536
3537                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, rgctx_reg, rgctx->dreg, MONO_STRUCT_OFFSET (MonoVTable, runtime_generic_context));
3538                 // FIXME: Avoid this check by allocating the table when the vtable is created etc.
3539                 NEW_BBLOCK (cfg, is_null_bb);
3540
3541                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, rgctx_reg, 0);
3542                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, is_null_bb);
3543         }
3544
3545         for (i = 0; i < depth; ++i) {
3546                 int array_reg = alloc_preg (cfg);
3547
3548                 /* load ptr to next array */
3549                 if (mrgctx && i == 0)
3550                         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, array_reg, rgctx_reg, MONO_SIZEOF_METHOD_RUNTIME_GENERIC_CONTEXT);
3551                 else
3552                         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, array_reg, rgctx_reg, 0);
3553                 rgctx_reg = array_reg;
3554                 /* is the ptr null? */
3555                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, rgctx_reg, 0);
3556                 /* if yes, jump to actual trampoline */
3557                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, is_null_bb);
3558         }
3559
3560         /* fetch slot */
3561         val_reg = alloc_preg (cfg);
3562         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, val_reg, rgctx_reg, (index + 1) * sizeof (gpointer));
3563         /* is the slot null? */
3564         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, val_reg, 0);
3565         /* if yes, jump to actual trampoline */
3566         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, is_null_bb);
3567
3568         /* Fastpath */
3569         res_reg = alloc_preg (cfg);
3570         MONO_INST_NEW (cfg, ins, OP_MOVE);
3571         ins->dreg = res_reg;
3572         ins->sreg1 = val_reg;
3573         MONO_ADD_INS (cfg->cbb, ins);
3574         res = ins;
3575         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
3576
3577         /* Slowpath */
3578         MONO_START_BB (cfg, is_null_bb);
3579         args [0] = rgctx;
3580         EMIT_NEW_ICONST (cfg, args [1], index);
3581         if (mrgctx)
3582                 call = mono_emit_jit_icall (cfg, mono_fill_method_rgctx, args);
3583         else
3584                 call = mono_emit_jit_icall (cfg, mono_fill_class_rgctx, args);
3585         MONO_INST_NEW (cfg, ins, OP_MOVE);
3586         ins->dreg = res_reg;
3587         ins->sreg1 = call->dreg;
3588         MONO_ADD_INS (cfg->cbb, ins);
3589         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
3590
3591         MONO_START_BB (cfg, end_bb);
3592
3593         return res;
3594 #endif
3595 }
3596
3597 /*
3598  * emit_rgctx_fetch:
3599  *
3600  *   Emit IR to load the value of the rgctx entry ENTRY from the rgctx
3601  * given by RGCTX.
3602  */
3603 static inline MonoInst*
3604 emit_rgctx_fetch (MonoCompile *cfg, MonoInst *rgctx, MonoJumpInfoRgctxEntry *entry)
3605 {
3606         if (cfg->llvm_only)
3607                 return emit_rgctx_fetch_inline (cfg, rgctx, entry);
3608         else
3609                 return mono_emit_abs_call (cfg, MONO_PATCH_INFO_RGCTX_FETCH, entry, helper_sig_rgctx_lazy_fetch_trampoline, &rgctx);
3610 }
3611
3612 static MonoInst*
3613 emit_get_rgctx_klass (MonoCompile *cfg, int context_used,
3614                                           MonoClass *klass, MonoRgctxInfoType rgctx_type)
3615 {
3616         MonoJumpInfoRgctxEntry *entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_CLASS, klass, rgctx_type);
3617         MonoInst *rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
3618
3619         return emit_rgctx_fetch (cfg, rgctx, entry);
3620 }
3621
3622 static MonoInst*
3623 emit_get_rgctx_sig (MonoCompile *cfg, int context_used,
3624                                         MonoMethodSignature *sig, MonoRgctxInfoType rgctx_type)
3625 {
3626         MonoJumpInfoRgctxEntry *entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_SIGNATURE, sig, rgctx_type);
3627         MonoInst *rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
3628
3629         return emit_rgctx_fetch (cfg, rgctx, entry);
3630 }
3631
3632 static MonoInst*
3633 emit_get_rgctx_gsharedvt_call (MonoCompile *cfg, int context_used,
3634                                                            MonoMethodSignature *sig, MonoMethod *cmethod, MonoRgctxInfoType rgctx_type)
3635 {
3636         MonoJumpInfoGSharedVtCall *call_info;
3637         MonoJumpInfoRgctxEntry *entry;
3638         MonoInst *rgctx;
3639
3640         call_info = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoJumpInfoGSharedVtCall));
3641         call_info->sig = sig;
3642         call_info->method = cmethod;
3643
3644         entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_GSHAREDVT_CALL, call_info, rgctx_type);
3645         rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
3646
3647         return emit_rgctx_fetch (cfg, rgctx, entry);
3648 }
3649
3650 /*
3651  * emit_get_rgctx_virt_method:
3652  *
3653  *   Return data for method VIRT_METHOD for a receiver of type KLASS.
3654  */
3655 static MonoInst*
3656 emit_get_rgctx_virt_method (MonoCompile *cfg, int context_used,
3657                                                         MonoClass *klass, MonoMethod *virt_method, MonoRgctxInfoType rgctx_type)
3658 {
3659         MonoJumpInfoVirtMethod *info;
3660         MonoJumpInfoRgctxEntry *entry;
3661         MonoInst *rgctx;
3662
3663         info = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoJumpInfoVirtMethod));
3664         info->klass = klass;
3665         info->method = virt_method;
3666
3667         entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_VIRT_METHOD, info, rgctx_type);
3668         rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
3669
3670         return emit_rgctx_fetch (cfg, rgctx, entry);
3671 }
3672
3673 static MonoInst*
3674 emit_get_rgctx_gsharedvt_method (MonoCompile *cfg, int context_used,
3675                                                                  MonoMethod *cmethod, MonoGSharedVtMethodInfo *info)
3676 {
3677         MonoJumpInfoRgctxEntry *entry;
3678         MonoInst *rgctx;
3679
3680         entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_GSHAREDVT_METHOD, info, MONO_RGCTX_INFO_METHOD_GSHAREDVT_INFO);
3681         rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
3682
3683         return emit_rgctx_fetch (cfg, rgctx, entry);
3684 }
3685
3686 /*
3687  * emit_get_rgctx_method:
3688  *
3689  *   Emit IR to load the property RGCTX_TYPE of CMETHOD. If context_used is 0, emit
3690  * normal constants, else emit a load from the rgctx.
3691  */
3692 static MonoInst*
3693 emit_get_rgctx_method (MonoCompile *cfg, int context_used,
3694                                            MonoMethod *cmethod, MonoRgctxInfoType rgctx_type)
3695 {
3696         if (!context_used) {
3697                 MonoInst *ins;
3698
3699                 switch (rgctx_type) {
3700                 case MONO_RGCTX_INFO_METHOD:
3701                         EMIT_NEW_METHODCONST (cfg, ins, cmethod);
3702                         return ins;
3703                 case MONO_RGCTX_INFO_METHOD_RGCTX:
3704                         EMIT_NEW_METHOD_RGCTX_CONST (cfg, ins, cmethod);
3705                         return ins;
3706                 default:
3707                         g_assert_not_reached ();
3708                 }
3709         } else {
3710                 MonoJumpInfoRgctxEntry *entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_METHODCONST, cmethod, rgctx_type);
3711                 MonoInst *rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
3712
3713                 return emit_rgctx_fetch (cfg, rgctx, entry);
3714         }
3715 }
3716
3717 static MonoInst*
3718 emit_get_rgctx_field (MonoCompile *cfg, int context_used,
3719                                           MonoClassField *field, MonoRgctxInfoType rgctx_type)
3720 {
3721         MonoJumpInfoRgctxEntry *entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_FIELD, field, rgctx_type);
3722         MonoInst *rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
3723
3724         return emit_rgctx_fetch (cfg, rgctx, entry);
3725 }
3726
3727 static int
3728 get_gsharedvt_info_slot (MonoCompile *cfg, gpointer data, MonoRgctxInfoType rgctx_type)
3729 {
3730         MonoGSharedVtMethodInfo *info = cfg->gsharedvt_info;
3731         MonoRuntimeGenericContextInfoTemplate *template;
3732         int i, idx;
3733
3734         g_assert (info);
3735
3736         for (i = 0; i < info->num_entries; ++i) {
3737                 MonoRuntimeGenericContextInfoTemplate *otemplate = &info->entries [i];
3738
3739                 if (otemplate->info_type == rgctx_type && otemplate->data == data && rgctx_type != MONO_RGCTX_INFO_LOCAL_OFFSET)
3740                         return i;
3741         }
3742
3743         if (info->num_entries == info->count_entries) {
3744                 MonoRuntimeGenericContextInfoTemplate *new_entries;
3745                 int new_count_entries = info->count_entries ? info->count_entries * 2 : 16;
3746
3747                 new_entries = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoRuntimeGenericContextInfoTemplate) * new_count_entries);
3748
3749                 memcpy (new_entries, info->entries, sizeof (MonoRuntimeGenericContextInfoTemplate) * info->count_entries);
3750                 info->entries = new_entries;
3751                 info->count_entries = new_count_entries;
3752         }
3753
3754         idx = info->num_entries;
3755         template = &info->entries [idx];
3756         template->info_type = rgctx_type;
3757         template->data = data;
3758
3759         info->num_entries ++;
3760
3761         return idx;
3762 }
3763
3764 /*
3765  * emit_get_gsharedvt_info:
3766  *
3767  *   This is similar to emit_get_rgctx_.., but loads the data from the gsharedvt info var instead of calling an rgctx fetch trampoline.
3768  */
3769 static MonoInst*
3770 emit_get_gsharedvt_info (MonoCompile *cfg, gpointer data, MonoRgctxInfoType rgctx_type)
3771 {
3772         MonoInst *ins;
3773         int idx, dreg;
3774
3775         idx = get_gsharedvt_info_slot (cfg, data, rgctx_type);
3776         /* Load info->entries [idx] */
3777         dreg = alloc_preg (cfg);
3778         EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, dreg, cfg->gsharedvt_info_var->dreg, MONO_STRUCT_OFFSET (MonoGSharedVtMethodRuntimeInfo, entries) + (idx * sizeof (gpointer)));
3779
3780         return ins;
3781 }
3782
3783 static MonoInst*
3784 emit_get_gsharedvt_info_klass (MonoCompile *cfg, MonoClass *klass, MonoRgctxInfoType rgctx_type)
3785 {
3786         return emit_get_gsharedvt_info (cfg, &klass->byval_arg, rgctx_type);
3787 }
3788
3789 /*
3790  * On return the caller must check @klass for load errors.
3791  */
3792 static void
3793 emit_class_init (MonoCompile *cfg, MonoClass *klass)
3794 {
3795         MonoInst *vtable_arg;
3796         int context_used;
3797
3798         context_used = mini_class_check_context_used (cfg, klass);
3799
3800         if (context_used) {
3801                 vtable_arg = emit_get_rgctx_klass (cfg, context_used,
3802                                                                                    klass, MONO_RGCTX_INFO_VTABLE);
3803         } else {
3804                 MonoVTable *vtable = mono_class_vtable (cfg->domain, klass);
3805
3806                 if (!vtable)
3807                         return;
3808                 EMIT_NEW_VTABLECONST (cfg, vtable_arg, vtable);
3809         }
3810
3811         if (!COMPILE_LLVM (cfg) && cfg->backend->have_op_generic_class_init) {
3812                 MonoInst *ins;
3813
3814                 /*
3815                  * Using an opcode instead of emitting IR here allows the hiding of the call inside the opcode,
3816                  * so this doesn't have to clobber any regs and it doesn't break basic blocks.
3817                  */
3818                 MONO_INST_NEW (cfg, ins, OP_GENERIC_CLASS_INIT);
3819                 ins->sreg1 = vtable_arg->dreg;
3820                 MONO_ADD_INS (cfg->cbb, ins);
3821         } else {
3822                 static int byte_offset = -1;
3823                 static guint8 bitmask;
3824                 int bits_reg, inited_reg;
3825                 MonoBasicBlock *inited_bb;
3826                 MonoInst *args [16];
3827
3828                 if (byte_offset < 0)
3829                         mono_marshal_find_bitfield_offset (MonoVTable, initialized, &byte_offset, &bitmask);
3830
3831                 bits_reg = alloc_ireg (cfg);
3832                 inited_reg = alloc_ireg (cfg);
3833
3834                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU1_MEMBASE, bits_reg, vtable_arg->dreg, byte_offset);
3835                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, inited_reg, bits_reg, bitmask);
3836
3837                 NEW_BBLOCK (cfg, inited_bb);
3838
3839                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, inited_reg, 0);
3840                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, inited_bb);
3841
3842                 args [0] = vtable_arg;
3843                 mono_emit_jit_icall (cfg, mono_generic_class_init, args);
3844
3845                 MONO_START_BB (cfg, inited_bb);
3846         }
3847 }
3848
3849 static void
3850 emit_seq_point (MonoCompile *cfg, MonoMethod *method, guint8* ip, gboolean intr_loc, gboolean nonempty_stack)
3851 {
3852         MonoInst *ins;
3853
3854         if (cfg->gen_seq_points && cfg->method == method) {
3855                 NEW_SEQ_POINT (cfg, ins, ip - cfg->header->code, intr_loc);
3856                 if (nonempty_stack)
3857                         ins->flags |= MONO_INST_NONEMPTY_STACK;
3858                 MONO_ADD_INS (cfg->cbb, ins);
3859         }
3860 }
3861
3862 static void
3863 save_cast_details (MonoCompile *cfg, MonoClass *klass, int obj_reg, gboolean null_check)
3864 {
3865         if (mini_get_debug_options ()->better_cast_details) {
3866                 int vtable_reg = alloc_preg (cfg);
3867                 int klass_reg = alloc_preg (cfg);
3868                 MonoBasicBlock *is_null_bb = NULL;
3869                 MonoInst *tls_get;
3870                 int to_klass_reg, context_used;
3871
3872                 if (null_check) {
3873                         NEW_BBLOCK (cfg, is_null_bb);
3874
3875                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, obj_reg, 0);
3876                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, is_null_bb);
3877                 }
3878
3879                 tls_get = mono_get_jit_tls_intrinsic (cfg);
3880                 if (!tls_get) {
3881                         fprintf (stderr, "error: --debug=casts not supported on this platform.\n.");
3882                         exit (1);
3883                 }
3884
3885                 MONO_ADD_INS (cfg->cbb, tls_get);
3886                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable));
3887                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, klass));
3888
3889                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, tls_get->dreg, MONO_STRUCT_OFFSET (MonoJitTlsData, class_cast_from), klass_reg);
3890
3891                 context_used = mini_class_check_context_used (cfg, klass);
3892                 if (context_used) {
3893                         MonoInst *class_ins;
3894
3895                         class_ins = emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS);
3896                         to_klass_reg = class_ins->dreg;
3897                 } else {
3898                         to_klass_reg = alloc_preg (cfg);
3899                         MONO_EMIT_NEW_CLASSCONST (cfg, to_klass_reg, klass);
3900                 }
3901                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, tls_get->dreg, MONO_STRUCT_OFFSET (MonoJitTlsData, class_cast_to), to_klass_reg);
3902
3903                 if (null_check)
3904                         MONO_START_BB (cfg, is_null_bb);
3905         }
3906 }
3907
3908 static void
3909 reset_cast_details (MonoCompile *cfg)
3910 {
3911         /* Reset the variables holding the cast details */
3912         if (mini_get_debug_options ()->better_cast_details) {
3913                 MonoInst *tls_get = mono_get_jit_tls_intrinsic (cfg);
3914
3915                 MONO_ADD_INS (cfg->cbb, tls_get);
3916                 /* It is enough to reset the from field */
3917                 MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STORE_MEMBASE_IMM, tls_get->dreg, MONO_STRUCT_OFFSET (MonoJitTlsData, class_cast_from), 0);
3918         }
3919 }
3920
3921 /*
3922  * On return the caller must check @array_class for load errors
3923  */
3924 static void
3925 mini_emit_check_array_type (MonoCompile *cfg, MonoInst *obj, MonoClass *array_class)
3926 {
3927         int vtable_reg = alloc_preg (cfg);
3928         int context_used;
3929
3930         context_used = mini_class_check_context_used (cfg, array_class);
3931
3932         save_cast_details (cfg, array_class, obj->dreg, FALSE);
3933
3934         MONO_EMIT_NEW_LOAD_MEMBASE_FAULT (cfg, vtable_reg, obj->dreg, MONO_STRUCT_OFFSET (MonoObject, vtable));
3935
3936         if (cfg->opt & MONO_OPT_SHARED) {
3937                 int class_reg = alloc_preg (cfg);
3938                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, class_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, klass));
3939                 if (cfg->compile_aot) {
3940                         int klass_reg = alloc_preg (cfg);
3941                         MONO_EMIT_NEW_CLASSCONST (cfg, klass_reg, array_class);
3942                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, class_reg, klass_reg);
3943                 } else {
3944                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, class_reg, array_class);
3945                 }
3946         } else if (context_used) {
3947                 MonoInst *vtable_ins;
3948
3949                 vtable_ins = emit_get_rgctx_klass (cfg, context_used, array_class, MONO_RGCTX_INFO_VTABLE);
3950                 MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, vtable_reg, vtable_ins->dreg);
3951         } else {
3952                 if (cfg->compile_aot) {
3953                         int vt_reg;
3954                         MonoVTable *vtable;
3955
3956                         if (!(vtable = mono_class_vtable (cfg->domain, array_class)))
3957                                 return;
3958                         vt_reg = alloc_preg (cfg);
3959                         MONO_EMIT_NEW_VTABLECONST (cfg, vt_reg, vtable);
3960                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, vtable_reg, vt_reg);
3961                 } else {
3962                         MonoVTable *vtable;
3963                         if (!(vtable = mono_class_vtable (cfg->domain, array_class)))
3964                                 return;
3965                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, vtable_reg, vtable);
3966                 }
3967         }
3968         
3969         MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "ArrayTypeMismatchException");
3970
3971         reset_cast_details (cfg);
3972 }
3973
3974 /**
3975  * Handles unbox of a Nullable<T>. If context_used is non zero, then shared 
3976  * generic code is generated.
3977  */
3978 static MonoInst*
3979 handle_unbox_nullable (MonoCompile* cfg, MonoInst* val, MonoClass* klass, int context_used)
3980 {
3981         MonoMethod* method = mono_class_get_method_from_name (klass, "Unbox", 1);
3982
3983         if (context_used) {
3984                 MonoInst *rgctx, *addr;
3985
3986                 /* FIXME: What if the class is shared?  We might not
3987                    have to get the address of the method from the
3988                    RGCTX. */
3989                 addr = emit_get_rgctx_method (cfg, context_used, method,
3990                                                                           MONO_RGCTX_INFO_GENERIC_METHOD_CODE);
3991
3992                 rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
3993
3994                 return mono_emit_calli (cfg, mono_method_signature (method), &val, addr, NULL, rgctx);
3995         } else {
3996                 gboolean pass_vtable, pass_mrgctx;
3997                 MonoInst *rgctx_arg = NULL;
3998
3999                 check_method_sharing (cfg, method, &pass_vtable, &pass_mrgctx);
4000                 g_assert (!pass_mrgctx);
4001
4002                 if (pass_vtable) {
4003                         MonoVTable *vtable = mono_class_vtable (cfg->domain, method->klass);
4004
4005                         g_assert (vtable);
4006                         EMIT_NEW_VTABLECONST (cfg, rgctx_arg, vtable);
4007                 }
4008
4009                 return mono_emit_method_call_full (cfg, method, NULL, FALSE, &val, NULL, NULL, rgctx_arg);
4010         }
4011 }
4012
4013 static MonoInst*
4014 handle_unbox (MonoCompile *cfg, MonoClass *klass, MonoInst **sp, int context_used)
4015 {
4016         MonoInst *add;
4017         int obj_reg;
4018         int vtable_reg = alloc_dreg (cfg ,STACK_PTR);
4019         int klass_reg = alloc_dreg (cfg ,STACK_PTR);
4020         int eclass_reg = alloc_dreg (cfg ,STACK_PTR);
4021         int rank_reg = alloc_dreg (cfg ,STACK_I4);
4022
4023         obj_reg = sp [0]->dreg;
4024         MONO_EMIT_NEW_LOAD_MEMBASE_FAULT (cfg, vtable_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable));
4025         MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU1_MEMBASE, rank_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, rank));
4026
4027         /* FIXME: generics */
4028         g_assert (klass->rank == 0);
4029                         
4030         // Check rank == 0
4031         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, rank_reg, 0);
4032         MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "InvalidCastException");
4033
4034         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, klass));
4035         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, eclass_reg, klass_reg, MONO_STRUCT_OFFSET (MonoClass, element_class));
4036
4037         if (context_used) {
4038                 MonoInst *element_class;
4039
4040                 /* This assertion is from the unboxcast insn */
4041                 g_assert (klass->rank == 0);
4042
4043                 element_class = emit_get_rgctx_klass (cfg, context_used,
4044                                 klass, MONO_RGCTX_INFO_ELEMENT_KLASS);
4045
4046                 MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, eclass_reg, element_class->dreg);
4047                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "InvalidCastException");
4048         } else {
4049                 save_cast_details (cfg, klass->element_class, obj_reg, FALSE);
4050                 mini_emit_class_check (cfg, eclass_reg, klass->element_class);
4051                 reset_cast_details (cfg);
4052         }
4053
4054         NEW_BIALU_IMM (cfg, add, OP_ADD_IMM, alloc_dreg (cfg, STACK_MP), obj_reg, sizeof (MonoObject));
4055         MONO_ADD_INS (cfg->cbb, add);
4056         add->type = STACK_MP;
4057         add->klass = klass;
4058
4059         return add;
4060 }
4061
4062 static MonoInst*
4063 handle_unbox_gsharedvt (MonoCompile *cfg, MonoClass *klass, MonoInst *obj)
4064 {
4065         MonoInst *addr, *klass_inst, *is_ref, *args[16];
4066         MonoBasicBlock *is_ref_bb, *is_nullable_bb, *end_bb;
4067         MonoInst *ins;
4068         int dreg, addr_reg;
4069
4070         klass_inst = emit_get_gsharedvt_info_klass (cfg, klass, MONO_RGCTX_INFO_KLASS);
4071
4072         /* obj */
4073         args [0] = obj;
4074
4075         /* klass */
4076         args [1] = klass_inst;
4077
4078         /* CASTCLASS */
4079         obj = mono_emit_jit_icall (cfg, mono_object_castclass_unbox, args);
4080
4081         NEW_BBLOCK (cfg, is_ref_bb);
4082         NEW_BBLOCK (cfg, is_nullable_bb);
4083         NEW_BBLOCK (cfg, end_bb);
4084         is_ref = emit_get_gsharedvt_info_klass (cfg, klass, MONO_RGCTX_INFO_CLASS_BOX_TYPE);
4085         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, is_ref->dreg, 1);
4086         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, is_ref_bb);
4087
4088         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, is_ref->dreg, 2);
4089         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, is_nullable_bb);
4090
4091         /* This will contain either the address of the unboxed vtype, or an address of the temporary where the ref is stored */
4092         addr_reg = alloc_dreg (cfg, STACK_MP);
4093
4094         /* Non-ref case */
4095         /* UNBOX */
4096         NEW_BIALU_IMM (cfg, addr, OP_ADD_IMM, addr_reg, obj->dreg, sizeof (MonoObject));
4097         MONO_ADD_INS (cfg->cbb, addr);
4098
4099         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
4100
4101         /* Ref case */
4102         MONO_START_BB (cfg, is_ref_bb);
4103
4104         /* Save the ref to a temporary */
4105         dreg = alloc_ireg (cfg);
4106         EMIT_NEW_VARLOADA_VREG (cfg, addr, dreg, &klass->byval_arg);
4107         addr->dreg = addr_reg;
4108         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, addr->dreg, 0, obj->dreg);
4109         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
4110
4111         /* Nullable case */
4112         MONO_START_BB (cfg, is_nullable_bb);
4113
4114         {
4115                 MonoInst *addr = emit_get_gsharedvt_info_klass (cfg, klass, MONO_RGCTX_INFO_NULLABLE_CLASS_UNBOX);
4116                 MonoInst *unbox_call;
4117                 MonoMethodSignature *unbox_sig;
4118
4119                 unbox_sig = mono_mempool_alloc0 (cfg->mempool, MONO_SIZEOF_METHOD_SIGNATURE + (1 * sizeof (MonoType *)));
4120                 unbox_sig->ret = &klass->byval_arg;
4121                 unbox_sig->param_count = 1;
4122                 unbox_sig->params [0] = &mono_defaults.object_class->byval_arg;
4123                 unbox_call = mono_emit_calli (cfg, unbox_sig, &obj, addr, NULL, NULL);
4124
4125                 EMIT_NEW_VARLOADA_VREG (cfg, addr, unbox_call->dreg, &klass->byval_arg);
4126                 addr->dreg = addr_reg;
4127         }
4128
4129         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
4130
4131         /* End */
4132         MONO_START_BB (cfg, end_bb);
4133
4134         /* LDOBJ */
4135         EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, addr_reg, 0);
4136
4137         return ins;
4138 }
4139
4140 /*
4141  * Returns NULL and set the cfg exception on error.
4142  */
4143 static MonoInst*
4144 handle_alloc (MonoCompile *cfg, MonoClass *klass, gboolean for_box, int context_used)
4145 {
4146         MonoInst *iargs [2];
4147         void *alloc_ftn;
4148
4149         if (context_used) {
4150                 MonoInst *data;
4151                 int rgctx_info;
4152                 MonoInst *iargs [2];
4153                 gboolean known_instance_size = !mini_is_gsharedvt_klass (klass);
4154
4155                 MonoMethod *managed_alloc = mono_gc_get_managed_allocator (klass, for_box, known_instance_size);
4156
4157                 if (cfg->opt & MONO_OPT_SHARED)
4158                         rgctx_info = MONO_RGCTX_INFO_KLASS;
4159                 else
4160                         rgctx_info = MONO_RGCTX_INFO_VTABLE;
4161                 data = emit_get_rgctx_klass (cfg, context_used, klass, rgctx_info);
4162
4163                 if (cfg->opt & MONO_OPT_SHARED) {
4164                         EMIT_NEW_DOMAINCONST (cfg, iargs [0]);
4165                         iargs [1] = data;
4166                         alloc_ftn = mono_object_new;
4167                 } else {
4168                         iargs [0] = data;
4169                         alloc_ftn = mono_object_new_specific;
4170                 }
4171
4172                 if (managed_alloc && !(cfg->opt & MONO_OPT_SHARED)) {
4173                         if (known_instance_size) {
4174                                 int size = mono_class_instance_size (klass);
4175                                 if (size < sizeof (MonoObject))
4176                                         g_error ("Invalid size %d for class %s", size, mono_type_get_full_name (klass));
4177
4178                                 EMIT_NEW_ICONST (cfg, iargs [1], mono_gc_get_aligned_size_for_allocator (size));
4179                         }
4180                         return mono_emit_method_call (cfg, managed_alloc, iargs, NULL);
4181                 }
4182
4183                 return mono_emit_jit_icall (cfg, alloc_ftn, iargs);
4184         }
4185
4186         if (cfg->opt & MONO_OPT_SHARED) {
4187                 EMIT_NEW_DOMAINCONST (cfg, iargs [0]);
4188                 EMIT_NEW_CLASSCONST (cfg, iargs [1], klass);
4189
4190                 alloc_ftn = mono_object_new;
4191         } else if (cfg->compile_aot && cfg->cbb->out_of_line && klass->type_token && klass->image == mono_defaults.corlib && !klass->generic_class) {
4192                 /* This happens often in argument checking code, eg. throw new FooException... */
4193                 /* Avoid relocations and save some space by calling a helper function specialized to mscorlib */
4194                 EMIT_NEW_ICONST (cfg, iargs [0], mono_metadata_token_index (klass->type_token));
4195                 return mono_emit_jit_icall (cfg, mono_helper_newobj_mscorlib, iargs);
4196         } else {
4197                 MonoVTable *vtable = mono_class_vtable (cfg->domain, klass);
4198                 MonoMethod *managed_alloc = NULL;
4199                 gboolean pass_lw;
4200
4201                 if (!vtable) {
4202                         mono_cfg_set_exception (cfg, MONO_EXCEPTION_TYPE_LOAD);
4203                         cfg->exception_ptr = klass;
4204                         return NULL;
4205                 }
4206
4207                 managed_alloc = mono_gc_get_managed_allocator (klass, for_box, TRUE);
4208
4209                 if (managed_alloc) {
4210                         int size = mono_class_instance_size (klass);
4211                         if (size < sizeof (MonoObject))
4212                                 g_error ("Invalid size %d for class %s", size, mono_type_get_full_name (klass));
4213
4214                         EMIT_NEW_VTABLECONST (cfg, iargs [0], vtable);
4215                         EMIT_NEW_ICONST (cfg, iargs [1], mono_gc_get_aligned_size_for_allocator (size));
4216                         return mono_emit_method_call (cfg, managed_alloc, iargs, NULL);
4217                 }
4218                 alloc_ftn = mono_class_get_allocation_ftn (vtable, for_box, &pass_lw);
4219                 if (pass_lw) {
4220                         guint32 lw = vtable->klass->instance_size;
4221                         lw = ((lw + (sizeof (gpointer) - 1)) & ~(sizeof (gpointer) - 1)) / sizeof (gpointer);
4222                         EMIT_NEW_ICONST (cfg, iargs [0], lw);
4223                         EMIT_NEW_VTABLECONST (cfg, iargs [1], vtable);
4224                 }
4225                 else {
4226                         EMIT_NEW_VTABLECONST (cfg, iargs [0], vtable);
4227                 }
4228         }
4229
4230         return mono_emit_jit_icall (cfg, alloc_ftn, iargs);
4231 }
4232         
4233 /*
4234  * Returns NULL and set the cfg exception on error.
4235  */     
4236 static MonoInst*
4237 handle_box (MonoCompile *cfg, MonoInst *val, MonoClass *klass, int context_used)
4238 {
4239         MonoInst *alloc, *ins;
4240
4241         if (mono_class_is_nullable (klass)) {
4242                 MonoMethod* method = mono_class_get_method_from_name (klass, "Box", 1);
4243
4244                 if (context_used) {
4245                         /* FIXME: What if the class is shared?  We might not
4246                            have to get the method address from the RGCTX. */
4247                         MonoInst *addr = emit_get_rgctx_method (cfg, context_used, method,
4248                                                                                                         MONO_RGCTX_INFO_GENERIC_METHOD_CODE);
4249                         MonoInst *rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
4250
4251                         return mono_emit_calli (cfg, mono_method_signature (method), &val, addr, NULL, rgctx);
4252                 } else {
4253                         gboolean pass_vtable, pass_mrgctx;
4254                         MonoInst *rgctx_arg = NULL;
4255
4256                         check_method_sharing (cfg, method, &pass_vtable, &pass_mrgctx);
4257                         g_assert (!pass_mrgctx);
4258
4259                         if (pass_vtable) {
4260                                 MonoVTable *vtable = mono_class_vtable (cfg->domain, method->klass);
4261
4262                                 g_assert (vtable);
4263                                 EMIT_NEW_VTABLECONST (cfg, rgctx_arg, vtable);
4264                         }
4265
4266                         return mono_emit_method_call_full (cfg, method, NULL, FALSE, &val, NULL, NULL, rgctx_arg);
4267                 }
4268         }
4269
4270         if (mini_is_gsharedvt_klass (klass)) {
4271                 MonoBasicBlock *is_ref_bb, *is_nullable_bb, *end_bb;
4272                 MonoInst *res, *is_ref, *src_var, *addr;
4273                 int dreg;
4274
4275                 dreg = alloc_ireg (cfg);
4276
4277                 NEW_BBLOCK (cfg, is_ref_bb);
4278                 NEW_BBLOCK (cfg, is_nullable_bb);
4279                 NEW_BBLOCK (cfg, end_bb);
4280                 is_ref = emit_get_gsharedvt_info_klass (cfg, klass, MONO_RGCTX_INFO_CLASS_BOX_TYPE);
4281                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, is_ref->dreg, 1);
4282                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, is_ref_bb);
4283
4284                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, is_ref->dreg, 2);
4285                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, is_nullable_bb);
4286
4287                 /* Non-ref case */
4288                 alloc = handle_alloc (cfg, klass, TRUE, context_used);
4289                 if (!alloc)
4290                         return NULL;
4291                 EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, alloc->dreg, sizeof (MonoObject), val->dreg);
4292                 ins->opcode = OP_STOREV_MEMBASE;
4293
4294                 EMIT_NEW_UNALU (cfg, res, OP_MOVE, dreg, alloc->dreg);
4295                 res->type = STACK_OBJ;
4296                 res->klass = klass;
4297                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
4298                 
4299                 /* Ref case */
4300                 MONO_START_BB (cfg, is_ref_bb);
4301
4302                 /* val is a vtype, so has to load the value manually */
4303                 src_var = get_vreg_to_inst (cfg, val->dreg);
4304                 if (!src_var)
4305                         src_var = mono_compile_create_var_for_vreg (cfg, &klass->byval_arg, OP_LOCAL, val->dreg);
4306                 EMIT_NEW_VARLOADA (cfg, addr, src_var, src_var->inst_vtype);
4307                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, addr->dreg, 0);
4308                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
4309
4310                 /* Nullable case */
4311                 MONO_START_BB (cfg, is_nullable_bb);
4312
4313                 {
4314                         MonoInst *addr = emit_get_gsharedvt_info_klass (cfg, klass,
4315                                                                                                         MONO_RGCTX_INFO_NULLABLE_CLASS_BOX);
4316                         MonoInst *box_call;
4317                         MonoMethodSignature *box_sig;
4318
4319                         /*
4320                          * klass is Nullable<T>, need to call Nullable<T>.Box () using a gsharedvt signature, but we cannot
4321                          * construct that method at JIT time, so have to do things by hand.
4322                          */
4323                         box_sig = mono_mempool_alloc0 (cfg->mempool, MONO_SIZEOF_METHOD_SIGNATURE + (1 * sizeof (MonoType *)));
4324                         box_sig->ret = &mono_defaults.object_class->byval_arg;
4325                         box_sig->param_count = 1;
4326                         box_sig->params [0] = &klass->byval_arg;
4327                         box_call = mono_emit_calli (cfg, box_sig, &val, addr, NULL, NULL);
4328                         EMIT_NEW_UNALU (cfg, res, OP_MOVE, dreg, box_call->dreg);
4329                         res->type = STACK_OBJ;
4330                         res->klass = klass;
4331                 }
4332
4333                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
4334
4335                 MONO_START_BB (cfg, end_bb);
4336
4337                 return res;
4338         } else {
4339                 alloc = handle_alloc (cfg, klass, TRUE, context_used);
4340                 if (!alloc)
4341                         return NULL;
4342
4343                 EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, alloc->dreg, sizeof (MonoObject), val->dreg);
4344                 return alloc;
4345         }
4346 }
4347
4348 static gboolean
4349 mini_class_has_reference_variant_generic_argument (MonoCompile *cfg, MonoClass *klass, int context_used)
4350 {
4351         int i;
4352         MonoGenericContainer *container;
4353         MonoGenericInst *ginst;
4354
4355         if (klass->generic_class) {
4356                 container = klass->generic_class->container_class->generic_container;
4357                 ginst = klass->generic_class->context.class_inst;
4358         } else if (klass->generic_container && context_used) {
4359                 container = klass->generic_container;
4360                 ginst = container->context.class_inst;
4361         } else {
4362                 return FALSE;
4363         }
4364
4365         for (i = 0; i < container->type_argc; ++i) {
4366                 MonoType *type;
4367                 if (!(mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT)))
4368                         continue;
4369                 type = ginst->type_argv [i];
4370                 if (mini_type_is_reference (type))
4371                         return TRUE;
4372         }
4373         return FALSE;
4374 }
4375
4376 static GHashTable* direct_icall_type_hash;
4377
4378 static gboolean
4379 icall_is_direct_callable (MonoCompile *cfg, MonoMethod *cmethod)
4380 {
4381         /* LLVM on amd64 can't handle calls to non-32 bit addresses */
4382         if (!direct_icalls_enabled (cfg))
4383                 return FALSE;
4384
4385         /*
4386          * An icall is directly callable if it doesn't directly or indirectly call mono_raise_exception ().
4387          * Whitelist a few icalls for now.
4388          */
4389         if (!direct_icall_type_hash) {
4390                 GHashTable *h = g_hash_table_new (g_str_hash, g_str_equal);
4391
4392                 g_hash_table_insert (h, (char*)"Decimal", GUINT_TO_POINTER (1));
4393                 g_hash_table_insert (h, (char*)"Number", GUINT_TO_POINTER (1));
4394                 g_hash_table_insert (h, (char*)"Buffer", GUINT_TO_POINTER (1));
4395                 g_hash_table_insert (h, (char*)"Monitor", GUINT_TO_POINTER (1));
4396                 mono_memory_barrier ();
4397                 direct_icall_type_hash = h;
4398         }
4399
4400         if (cmethod->klass == mono_defaults.math_class)
4401                 return TRUE;
4402         /* No locking needed */
4403         if (cmethod->klass->image == mono_defaults.corlib && g_hash_table_lookup (direct_icall_type_hash, cmethod->klass->name))
4404                 return TRUE;
4405         return FALSE;
4406 }
4407
4408 #define is_complex_isinst(klass) ((klass->flags & TYPE_ATTRIBUTE_INTERFACE) || klass->rank || mono_class_is_nullable (klass) || mono_class_is_marshalbyref (klass) || (klass->flags & TYPE_ATTRIBUTE_SEALED) || klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
4409
4410 static MonoInst*
4411 emit_castclass_with_cache (MonoCompile *cfg, MonoClass *klass, MonoInst **args)
4412 {
4413         MonoMethod *mono_castclass;
4414         MonoInst *res;
4415
4416         mono_castclass = mono_marshal_get_castclass_with_cache ();
4417
4418         save_cast_details (cfg, klass, args [0]->dreg, TRUE);
4419         res = mono_emit_method_call (cfg, mono_castclass, args, NULL);
4420         reset_cast_details (cfg);
4421
4422         return res;
4423 }
4424
4425 static int
4426 get_castclass_cache_idx (MonoCompile *cfg)
4427 {
4428         /* Each CASTCLASS_CACHE patch needs a unique index which identifies the call site */
4429         cfg->castclass_cache_index ++;
4430         return (cfg->method_index << 16) | cfg->castclass_cache_index;
4431 }
4432
4433 static MonoInst*
4434 emit_castclass_with_cache_nonshared (MonoCompile *cfg, MonoInst *obj, MonoClass *klass)
4435 {
4436         MonoInst *args [3];
4437         int idx;
4438
4439         /* obj */
4440         args [0] = obj;
4441
4442         /* klass */
4443         EMIT_NEW_CLASSCONST (cfg, args [1], klass);
4444
4445         /* inline cache*/
4446         if (cfg->compile_aot) {
4447                 idx = get_castclass_cache_idx (cfg);
4448                 EMIT_NEW_AOTCONST (cfg, args [2], MONO_PATCH_INFO_CASTCLASS_CACHE, GINT_TO_POINTER (idx));
4449         } else {
4450                 EMIT_NEW_PCONST (cfg, args [2], mono_domain_alloc0 (cfg->domain, sizeof (gpointer)));
4451         }
4452
4453         /*The wrapper doesn't inline well so the bloat of inlining doesn't pay off.*/
4454         return emit_castclass_with_cache (cfg, klass, args);
4455 }
4456
4457 /*
4458  * Returns NULL and set the cfg exception on error.
4459  */
4460 static MonoInst*
4461 handle_castclass (MonoCompile *cfg, MonoClass *klass, MonoInst *src, guint8 *ip, int *inline_costs)
4462 {
4463         MonoBasicBlock *is_null_bb;
4464         int obj_reg = src->dreg;
4465         int vtable_reg = alloc_preg (cfg);
4466         int context_used;
4467         MonoInst *klass_inst = NULL, *res;
4468
4469         context_used = mini_class_check_context_used (cfg, klass);
4470
4471         if (!context_used && mini_class_has_reference_variant_generic_argument (cfg, klass, context_used)) {
4472                 res = emit_castclass_with_cache_nonshared (cfg, src, klass);
4473                 (*inline_costs) += 2;
4474                 return res;
4475         } else if (!context_used && (mono_class_is_marshalbyref (klass) || klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
4476                 MonoMethod *mono_castclass;
4477                 MonoInst *iargs [1];
4478                 int costs;
4479
4480                 mono_castclass = mono_marshal_get_castclass (klass); 
4481                 iargs [0] = src;
4482                                 
4483                 save_cast_details (cfg, klass, src->dreg, TRUE);
4484                 costs = inline_method (cfg, mono_castclass, mono_method_signature (mono_castclass), 
4485                                                            iargs, ip, cfg->real_offset, TRUE);
4486                 reset_cast_details (cfg);
4487                 CHECK_CFG_EXCEPTION;
4488                 g_assert (costs > 0);
4489                                 
4490                 cfg->real_offset += 5;
4491
4492                 (*inline_costs) += costs;
4493
4494                 return src;
4495         }
4496
4497         if (context_used) {
4498                 MonoInst *args [3];
4499
4500                 if(mini_class_has_reference_variant_generic_argument (cfg, klass, context_used) || is_complex_isinst (klass)) {
4501                         MonoInst *cache_ins;
4502
4503                         cache_ins = emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_CAST_CACHE);
4504
4505                         /* obj */
4506                         args [0] = src;
4507
4508                         /* klass - it's the second element of the cache entry*/
4509                         EMIT_NEW_LOAD_MEMBASE (cfg, args [1], OP_LOAD_MEMBASE, alloc_preg (cfg), cache_ins->dreg, sizeof (gpointer));
4510
4511                         /* cache */
4512                         args [2] = cache_ins;
4513
4514                         return emit_castclass_with_cache (cfg, klass, args);
4515                 }
4516
4517                 klass_inst = emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS);
4518         }
4519
4520         NEW_BBLOCK (cfg, is_null_bb);
4521
4522         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, obj_reg, 0);
4523         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, is_null_bb);
4524
4525         save_cast_details (cfg, klass, obj_reg, FALSE);
4526
4527         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
4528                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable));
4529                 mini_emit_iface_cast (cfg, vtable_reg, klass, NULL, NULL);
4530         } else {
4531                 int klass_reg = alloc_preg (cfg);
4532
4533                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable));
4534
4535                 if (!klass->rank && !cfg->compile_aot && !(cfg->opt & MONO_OPT_SHARED) && (klass->flags & TYPE_ATTRIBUTE_SEALED)) {
4536                         /* the remoting code is broken, access the class for now */
4537                         if (0) { /*FIXME what exactly is broken? This change refers to r39380 from 2005 and mention some remoting fixes were due.*/
4538                                 MonoVTable *vt = mono_class_vtable (cfg->domain, klass);
4539                                 if (!vt) {
4540                                         mono_cfg_set_exception (cfg, MONO_EXCEPTION_TYPE_LOAD);
4541                                         cfg->exception_ptr = klass;
4542                                         return NULL;
4543                                 }
4544                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, vtable_reg, vt);
4545                         } else {
4546                                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, klass));
4547                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, klass_reg, klass);
4548                         }
4549                         MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "InvalidCastException");
4550                 } else {
4551                         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, klass));
4552                         mini_emit_castclass_inst (cfg, obj_reg, klass_reg, klass, klass_inst, is_null_bb);
4553                 }
4554         }
4555
4556         MONO_START_BB (cfg, is_null_bb);
4557
4558         reset_cast_details (cfg);
4559
4560         return src;
4561
4562 exception_exit:
4563         return NULL;
4564 }
4565
4566 /*
4567  * Returns NULL and set the cfg exception on error.
4568  */
4569 static MonoInst*
4570 handle_isinst (MonoCompile *cfg, MonoClass *klass, MonoInst *src, int context_used)
4571 {
4572         MonoInst *ins;
4573         MonoBasicBlock *is_null_bb, *false_bb, *end_bb;
4574         int obj_reg = src->dreg;
4575         int vtable_reg = alloc_preg (cfg);
4576         int res_reg = alloc_ireg_ref (cfg);
4577         MonoInst *klass_inst = NULL;
4578
4579         if (context_used) {
4580                 MonoInst *args [3];
4581
4582                 if(mini_class_has_reference_variant_generic_argument (cfg, klass, context_used) || is_complex_isinst (klass)) {
4583                         MonoMethod *mono_isinst = mono_marshal_get_isinst_with_cache ();
4584                         MonoInst *cache_ins;
4585
4586                         cache_ins = emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_CAST_CACHE);
4587
4588                         /* obj */
4589                         args [0] = src;
4590
4591                         /* klass - it's the second element of the cache entry*/
4592                         EMIT_NEW_LOAD_MEMBASE (cfg, args [1], OP_LOAD_MEMBASE, alloc_preg (cfg), cache_ins->dreg, sizeof (gpointer));
4593
4594                         /* cache */
4595                         args [2] = cache_ins;
4596
4597                         return mono_emit_method_call (cfg, mono_isinst, args, NULL);
4598                 }
4599
4600                 klass_inst = emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS);
4601         }
4602
4603         NEW_BBLOCK (cfg, is_null_bb);
4604         NEW_BBLOCK (cfg, false_bb);
4605         NEW_BBLOCK (cfg, end_bb);
4606
4607         /* Do the assignment at the beginning, so the other assignment can be if converted */
4608         EMIT_NEW_UNALU (cfg, ins, OP_MOVE, res_reg, obj_reg);
4609         ins->type = STACK_OBJ;
4610         ins->klass = klass;
4611
4612         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, obj_reg, 0);
4613         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, is_null_bb);
4614
4615         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable));
4616
4617         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
4618                 g_assert (!context_used);
4619                 /* the is_null_bb target simply copies the input register to the output */
4620                 mini_emit_iface_cast (cfg, vtable_reg, klass, false_bb, is_null_bb);
4621         } else {
4622                 int klass_reg = alloc_preg (cfg);
4623
4624                 if (klass->rank) {
4625                         int rank_reg = alloc_preg (cfg);
4626                         int eclass_reg = alloc_preg (cfg);
4627
4628                         g_assert (!context_used);
4629                         MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU1_MEMBASE, rank_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, rank));
4630                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, rank_reg, klass->rank);
4631                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, false_bb);
4632                         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, klass));
4633                         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, eclass_reg, klass_reg, MONO_STRUCT_OFFSET (MonoClass, cast_class));
4634                         if (klass->cast_class == mono_defaults.object_class) {
4635                                 int parent_reg = alloc_preg (cfg);
4636                                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, parent_reg, eclass_reg, MONO_STRUCT_OFFSET (MonoClass, parent));
4637                                 mini_emit_class_check_branch (cfg, parent_reg, mono_defaults.enum_class->parent, OP_PBNE_UN, is_null_bb);
4638                                 mini_emit_class_check_branch (cfg, eclass_reg, mono_defaults.enum_class, OP_PBEQ, is_null_bb);
4639                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, false_bb);
4640                         } else if (klass->cast_class == mono_defaults.enum_class->parent) {
4641                                 mini_emit_class_check_branch (cfg, eclass_reg, mono_defaults.enum_class->parent, OP_PBEQ, is_null_bb);
4642                                 mini_emit_class_check_branch (cfg, eclass_reg, mono_defaults.enum_class, OP_PBEQ, is_null_bb);                          
4643                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, false_bb);
4644                         } else if (klass->cast_class == mono_defaults.enum_class) {
4645                                 mini_emit_class_check_branch (cfg, eclass_reg, mono_defaults.enum_class, OP_PBEQ, is_null_bb);
4646                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, false_bb);
4647                         } else if (klass->cast_class->flags & TYPE_ATTRIBUTE_INTERFACE) {
4648                                 mini_emit_iface_class_cast (cfg, eclass_reg, klass->cast_class, false_bb, is_null_bb);
4649                         } else {
4650                                 if ((klass->rank == 1) && (klass->byval_arg.type == MONO_TYPE_SZARRAY)) {
4651                                         /* Check that the object is a vector too */
4652                                         int bounds_reg = alloc_preg (cfg);
4653                                         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, bounds_reg, obj_reg, MONO_STRUCT_OFFSET (MonoArray, bounds));
4654                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, bounds_reg, 0);
4655                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, false_bb);
4656                                 }
4657
4658                                 /* the is_null_bb target simply copies the input register to the output */
4659                                 mini_emit_isninst_cast (cfg, eclass_reg, klass->cast_class, false_bb, is_null_bb);
4660                         }
4661                 } else if (mono_class_is_nullable (klass)) {
4662                         g_assert (!context_used);
4663                         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, klass));
4664                         /* the is_null_bb target simply copies the input register to the output */
4665                         mini_emit_isninst_cast (cfg, klass_reg, klass->cast_class, false_bb, is_null_bb);
4666                 } else {
4667                         if (!cfg->compile_aot && !(cfg->opt & MONO_OPT_SHARED) && (klass->flags & TYPE_ATTRIBUTE_SEALED)) {
4668                                 g_assert (!context_used);
4669                                 /* the remoting code is broken, access the class for now */
4670                                 if (0) {/*FIXME what exactly is broken? This change refers to r39380 from 2005 and mention some remoting fixes were due.*/
4671                                         MonoVTable *vt = mono_class_vtable (cfg->domain, klass);
4672                                         if (!vt) {
4673                                                 mono_cfg_set_exception (cfg, MONO_EXCEPTION_TYPE_LOAD);
4674                                                 cfg->exception_ptr = klass;
4675                                                 return NULL;
4676                                         }
4677                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, vtable_reg, vt);
4678                                 } else {
4679                                         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, klass));
4680                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, klass_reg, klass);
4681                                 }
4682                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, false_bb);
4683                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, is_null_bb);
4684                         } else {
4685                                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, klass));
4686                                 /* the is_null_bb target simply copies the input register to the output */
4687                                 mini_emit_isninst_cast_inst (cfg, klass_reg, klass, klass_inst, false_bb, is_null_bb);
4688                         }
4689                 }
4690         }
4691
4692         MONO_START_BB (cfg, false_bb);
4693
4694         MONO_EMIT_NEW_PCONST (cfg, res_reg, 0);
4695         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
4696
4697         MONO_START_BB (cfg, is_null_bb);
4698
4699         MONO_START_BB (cfg, end_bb);
4700
4701         return ins;
4702 }
4703
4704 static MonoInst*
4705 handle_cisinst (MonoCompile *cfg, MonoClass *klass, MonoInst *src)
4706 {
4707         /* This opcode takes as input an object reference and a class, and returns:
4708         0) if the object is an instance of the class,
4709         1) if the object is not instance of the class,
4710         2) if the object is a proxy whose type cannot be determined */
4711
4712         MonoInst *ins;
4713 #ifndef DISABLE_REMOTING
4714         MonoBasicBlock *true_bb, *false_bb, *false2_bb, *end_bb, *no_proxy_bb, *interface_fail_bb;
4715 #else
4716         MonoBasicBlock *true_bb, *false_bb, *end_bb;
4717 #endif
4718         int obj_reg = src->dreg;
4719         int dreg = alloc_ireg (cfg);
4720         int tmp_reg;
4721 #ifndef DISABLE_REMOTING
4722         int klass_reg = alloc_preg (cfg);
4723 #endif
4724
4725         NEW_BBLOCK (cfg, true_bb);
4726         NEW_BBLOCK (cfg, false_bb);
4727         NEW_BBLOCK (cfg, end_bb);
4728 #ifndef DISABLE_REMOTING
4729         NEW_BBLOCK (cfg, false2_bb);
4730         NEW_BBLOCK (cfg, no_proxy_bb);
4731 #endif
4732
4733         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, obj_reg, 0);
4734         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, false_bb);
4735
4736         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
4737 #ifndef DISABLE_REMOTING
4738                 NEW_BBLOCK (cfg, interface_fail_bb);
4739 #endif
4740
4741                 tmp_reg = alloc_preg (cfg);
4742                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable));
4743 #ifndef DISABLE_REMOTING
4744                 mini_emit_iface_cast (cfg, tmp_reg, klass, interface_fail_bb, true_bb);
4745                 MONO_START_BB (cfg, interface_fail_bb);
4746                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, tmp_reg, MONO_STRUCT_OFFSET (MonoVTable, klass));
4747                 
4748                 mini_emit_class_check_branch (cfg, klass_reg, mono_defaults.transparent_proxy_class, OP_PBNE_UN, false_bb);
4749
4750                 tmp_reg = alloc_preg (cfg);
4751                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info));
4752                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tmp_reg, 0);
4753                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, false2_bb);                
4754 #else
4755                 mini_emit_iface_cast (cfg, tmp_reg, klass, false_bb, true_bb);
4756 #endif
4757         } else {
4758 #ifndef DISABLE_REMOTING
4759                 tmp_reg = alloc_preg (cfg);
4760                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable));
4761                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, tmp_reg, MONO_STRUCT_OFFSET (MonoVTable, klass));
4762
4763                 mini_emit_class_check_branch (cfg, klass_reg, mono_defaults.transparent_proxy_class, OP_PBNE_UN, no_proxy_bb);          
4764                 tmp_reg = alloc_preg (cfg);
4765                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoTransparentProxy, remote_class));
4766                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, tmp_reg, MONO_STRUCT_OFFSET (MonoRemoteClass, proxy_class));
4767
4768                 tmp_reg = alloc_preg (cfg);             
4769                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info));
4770                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tmp_reg, 0);
4771                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, no_proxy_bb);
4772                 
4773                 mini_emit_isninst_cast (cfg, klass_reg, klass, false2_bb, true_bb);
4774                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, false2_bb);
4775
4776                 MONO_START_BB (cfg, no_proxy_bb);
4777
4778                 mini_emit_isninst_cast (cfg, klass_reg, klass, false_bb, true_bb);
4779 #else
4780                 g_error ("transparent proxy support is disabled while trying to JIT code that uses it");
4781 #endif
4782         }
4783
4784         MONO_START_BB (cfg, false_bb);
4785
4786         MONO_EMIT_NEW_ICONST (cfg, dreg, 1);
4787         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
4788
4789 #ifndef DISABLE_REMOTING
4790         MONO_START_BB (cfg, false2_bb);
4791
4792         MONO_EMIT_NEW_ICONST (cfg, dreg, 2);
4793         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
4794 #endif
4795
4796         MONO_START_BB (cfg, true_bb);
4797
4798         MONO_EMIT_NEW_ICONST (cfg, dreg, 0);
4799
4800         MONO_START_BB (cfg, end_bb);
4801
4802         /* FIXME: */
4803         MONO_INST_NEW (cfg, ins, OP_ICONST);
4804         ins->dreg = dreg;
4805         ins->type = STACK_I4;
4806
4807         return ins;
4808 }
4809
4810 static MonoInst*
4811 handle_ccastclass (MonoCompile *cfg, MonoClass *klass, MonoInst *src)
4812 {
4813         /* This opcode takes as input an object reference and a class, and returns:
4814         0) if the object is an instance of the class,
4815         1) if the object is a proxy whose type cannot be determined
4816         an InvalidCastException exception is thrown otherwhise*/
4817         
4818         MonoInst *ins;
4819 #ifndef DISABLE_REMOTING
4820         MonoBasicBlock *end_bb, *ok_result_bb, *no_proxy_bb, *interface_fail_bb, *fail_1_bb;
4821 #else
4822         MonoBasicBlock *ok_result_bb;
4823 #endif
4824         int obj_reg = src->dreg;
4825         int dreg = alloc_ireg (cfg);
4826         int tmp_reg = alloc_preg (cfg);
4827
4828 #ifndef DISABLE_REMOTING
4829         int klass_reg = alloc_preg (cfg);
4830         NEW_BBLOCK (cfg, end_bb);
4831 #endif
4832
4833         NEW_BBLOCK (cfg, ok_result_bb);
4834
4835         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, obj_reg, 0);
4836         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, ok_result_bb);
4837
4838         save_cast_details (cfg, klass, obj_reg, FALSE);
4839
4840         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
4841 #ifndef DISABLE_REMOTING
4842                 NEW_BBLOCK (cfg, interface_fail_bb);
4843         
4844                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable));
4845                 mini_emit_iface_cast (cfg, tmp_reg, klass, interface_fail_bb, ok_result_bb);
4846                 MONO_START_BB (cfg, interface_fail_bb);
4847                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, tmp_reg, MONO_STRUCT_OFFSET (MonoVTable, klass));
4848
4849                 mini_emit_class_check (cfg, klass_reg, mono_defaults.transparent_proxy_class);
4850
4851                 tmp_reg = alloc_preg (cfg);             
4852                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info));
4853                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tmp_reg, 0);
4854                 MONO_EMIT_NEW_COND_EXC (cfg, EQ, "InvalidCastException");
4855                 
4856                 MONO_EMIT_NEW_ICONST (cfg, dreg, 1);
4857                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
4858 #else
4859                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable));
4860                 mini_emit_iface_cast (cfg, tmp_reg, klass, NULL, NULL);
4861                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, ok_result_bb);
4862 #endif
4863         } else {
4864 #ifndef DISABLE_REMOTING
4865                 NEW_BBLOCK (cfg, no_proxy_bb);
4866
4867                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable));
4868                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, tmp_reg, MONO_STRUCT_OFFSET (MonoVTable, klass));
4869                 mini_emit_class_check_branch (cfg, klass_reg, mono_defaults.transparent_proxy_class, OP_PBNE_UN, no_proxy_bb);          
4870
4871                 tmp_reg = alloc_preg (cfg);
4872                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoTransparentProxy, remote_class));
4873                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, tmp_reg, MONO_STRUCT_OFFSET (MonoRemoteClass, proxy_class));
4874
4875                 tmp_reg = alloc_preg (cfg);
4876                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info));
4877                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tmp_reg, 0);
4878                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, no_proxy_bb);
4879
4880                 NEW_BBLOCK (cfg, fail_1_bb);
4881                 
4882                 mini_emit_isninst_cast (cfg, klass_reg, klass, fail_1_bb, ok_result_bb);
4883
4884                 MONO_START_BB (cfg, fail_1_bb);
4885
4886                 MONO_EMIT_NEW_ICONST (cfg, dreg, 1);
4887                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
4888
4889                 MONO_START_BB (cfg, no_proxy_bb);
4890
4891                 mini_emit_castclass (cfg, obj_reg, klass_reg, klass, ok_result_bb);
4892 #else
4893                 g_error ("Transparent proxy support is disabled while trying to JIT code that uses it");
4894 #endif
4895         }
4896
4897         MONO_START_BB (cfg, ok_result_bb);
4898
4899         MONO_EMIT_NEW_ICONST (cfg, dreg, 0);
4900
4901 #ifndef DISABLE_REMOTING
4902         MONO_START_BB (cfg, end_bb);
4903 #endif
4904
4905         /* FIXME: */
4906         MONO_INST_NEW (cfg, ins, OP_ICONST);
4907         ins->dreg = dreg;
4908         ins->type = STACK_I4;
4909
4910         return ins;
4911 }
4912
4913 static G_GNUC_UNUSED MonoInst*
4914 handle_enum_has_flag (MonoCompile *cfg, MonoClass *klass, MonoInst *enum_this, MonoInst *enum_flag)
4915 {
4916         MonoType *enum_type = mono_type_get_underlying_type (&klass->byval_arg);
4917         guint32 load_opc = mono_type_to_load_membase (cfg, enum_type);
4918         gboolean is_i4;
4919
4920         switch (enum_type->type) {
4921         case MONO_TYPE_I8:
4922         case MONO_TYPE_U8:
4923 #if SIZEOF_REGISTER == 8
4924         case MONO_TYPE_I:
4925         case MONO_TYPE_U:
4926 #endif
4927                 is_i4 = FALSE;
4928                 break;
4929         default:
4930                 is_i4 = TRUE;
4931                 break;
4932         }
4933
4934         {
4935                 MonoInst *load, *and, *cmp, *ceq;
4936                 int enum_reg = is_i4 ? alloc_ireg (cfg) : alloc_lreg (cfg);
4937                 int and_reg = is_i4 ? alloc_ireg (cfg) : alloc_lreg (cfg);
4938                 int dest_reg = alloc_ireg (cfg);
4939
4940                 EMIT_NEW_LOAD_MEMBASE (cfg, load, load_opc, enum_reg, enum_this->dreg, 0);
4941                 EMIT_NEW_BIALU (cfg, and, is_i4 ? OP_IAND : OP_LAND, and_reg, enum_reg, enum_flag->dreg);
4942                 EMIT_NEW_BIALU (cfg, cmp, is_i4 ? OP_ICOMPARE : OP_LCOMPARE, -1, and_reg, enum_flag->dreg);
4943                 EMIT_NEW_UNALU (cfg, ceq, is_i4 ? OP_ICEQ : OP_LCEQ, dest_reg, -1);
4944
4945                 ceq->type = STACK_I4;
4946
4947                 if (!is_i4) {
4948                         load = mono_decompose_opcode (cfg, load);
4949                         and = mono_decompose_opcode (cfg, and);
4950                         cmp = mono_decompose_opcode (cfg, cmp);
4951                         ceq = mono_decompose_opcode (cfg, ceq);
4952                 }
4953
4954                 return ceq;
4955         }
4956 }
4957
4958 /*
4959  * Returns NULL and set the cfg exception on error.
4960  */
4961 static G_GNUC_UNUSED MonoInst*
4962 handle_delegate_ctor (MonoCompile *cfg, MonoClass *klass, MonoInst *target, MonoMethod *method, int context_used, gboolean virtual)
4963 {
4964         MonoInst *ptr;
4965         int dreg;
4966         gpointer trampoline;
4967         MonoInst *obj, *method_ins, *tramp_ins;
4968         MonoDomain *domain;
4969         guint8 **code_slot;
4970
4971         if (virtual && !cfg->llvm_only) {
4972                 MonoMethod *invoke = mono_get_delegate_invoke (klass);
4973                 g_assert (invoke);
4974
4975                 if (!mono_get_delegate_virtual_invoke_impl (mono_method_signature (invoke), context_used ? NULL : method))
4976                         return NULL;
4977         }
4978
4979         obj = handle_alloc (cfg, klass, FALSE, mono_class_check_context_used (klass));
4980         if (!obj)
4981                 return NULL;
4982
4983         if (cfg->llvm_only) {
4984                 MonoInst *args [16];
4985
4986                 /*
4987                  * If the method to be called needs an rgctx, we can't fall back to mono_delegate_ctor (), since it might receive
4988                  * the address of a gshared method. So use a JIT icall.
4989                  * FIXME: Optimize this.
4990                  */
4991                 args [0] = obj;
4992                 args [1] = target;
4993                 args [2] = emit_get_rgctx_method (cfg, context_used, method, MONO_RGCTX_INFO_METHOD);
4994                 mono_emit_jit_icall (cfg, virtual ? mono_init_delegate_virtual : mono_init_delegate, args);
4995
4996                 return obj;
4997         }
4998
4999         /* Inline the contents of mono_delegate_ctor */
5000
5001         /* Set target field */
5002         /* Optimize away setting of NULL target */
5003         if (!(target->opcode == OP_PCONST && target->inst_p0 == 0)) {
5004                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, target), target->dreg);
5005                 if (cfg->gen_write_barriers) {
5006                         dreg = alloc_preg (cfg);
5007                         EMIT_NEW_BIALU_IMM (cfg, ptr, OP_PADD_IMM, dreg, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, target));
5008                         emit_write_barrier (cfg, ptr, target);
5009                 }
5010         }
5011
5012         /* Set method field */
5013         method_ins = emit_get_rgctx_method (cfg, context_used, method, MONO_RGCTX_INFO_METHOD);
5014         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, method), method_ins->dreg);
5015
5016         /* 
5017          * To avoid looking up the compiled code belonging to the target method
5018          * in mono_delegate_trampoline (), we allocate a per-domain memory slot to
5019          * store it, and we fill it after the method has been compiled.
5020          */
5021         if (!method->dynamic && !(cfg->opt & MONO_OPT_SHARED)) {
5022                 MonoInst *code_slot_ins;
5023
5024                 if (context_used) {
5025                         code_slot_ins = emit_get_rgctx_method (cfg, context_used, method, MONO_RGCTX_INFO_METHOD_DELEGATE_CODE);
5026                 } else {
5027                         domain = mono_domain_get ();
5028                         mono_domain_lock (domain);
5029                         if (!domain_jit_info (domain)->method_code_hash)
5030                                 domain_jit_info (domain)->method_code_hash = g_hash_table_new (NULL, NULL);
5031                         code_slot = g_hash_table_lookup (domain_jit_info (domain)->method_code_hash, method);
5032                         if (!code_slot) {
5033                                 code_slot = mono_domain_alloc0 (domain, sizeof (gpointer));
5034                                 g_hash_table_insert (domain_jit_info (domain)->method_code_hash, method, code_slot);
5035                         }
5036                         mono_domain_unlock (domain);
5037
5038                         if (cfg->compile_aot)
5039                                 EMIT_NEW_AOTCONST (cfg, code_slot_ins, MONO_PATCH_INFO_METHOD_CODE_SLOT, method);
5040                         else
5041                                 EMIT_NEW_PCONST (cfg, code_slot_ins, code_slot);
5042                 }
5043                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, method_code), code_slot_ins->dreg);                
5044         }
5045
5046         if (cfg->compile_aot) {
5047                 MonoDelegateClassMethodPair *del_tramp;
5048
5049                 del_tramp = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoDelegateClassMethodPair));
5050                 del_tramp->klass = klass;
5051                 del_tramp->method = context_used ? NULL : method;
5052                 del_tramp->is_virtual = virtual;
5053                 EMIT_NEW_AOTCONST (cfg, tramp_ins, MONO_PATCH_INFO_DELEGATE_TRAMPOLINE, del_tramp);
5054         } else {
5055                 if (virtual)
5056                         trampoline = mono_create_delegate_virtual_trampoline (cfg->domain, klass, context_used ? NULL : method);
5057                 else
5058                         trampoline = mono_create_delegate_trampoline_info (cfg->domain, klass, context_used ? NULL : method);
5059                 EMIT_NEW_PCONST (cfg, tramp_ins, trampoline);
5060         }
5061
5062         /* Set invoke_impl field */
5063         if (virtual) {
5064                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, invoke_impl), tramp_ins->dreg);
5065         } else {
5066                 dreg = alloc_preg (cfg);
5067                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, tramp_ins->dreg, MONO_STRUCT_OFFSET (MonoDelegateTrampInfo, invoke_impl));
5068                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, invoke_impl), dreg);
5069
5070                 dreg = alloc_preg (cfg);
5071                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, tramp_ins->dreg, MONO_STRUCT_OFFSET (MonoDelegateTrampInfo, method_ptr));
5072                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr), dreg);
5073         }
5074
5075         dreg = alloc_preg (cfg);
5076         MONO_EMIT_NEW_ICONST (cfg, dreg, virtual ? 1 : 0);
5077         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, method_is_virtual), dreg);
5078
5079         /* All the checks which are in mono_delegate_ctor () are done by the delegate trampoline */
5080
5081         return obj;
5082 }
5083
5084 static MonoInst*
5085 handle_array_new (MonoCompile *cfg, int rank, MonoInst **sp, unsigned char *ip)
5086 {
5087         MonoJitICallInfo *info;
5088
5089         /* Need to register the icall so it gets an icall wrapper */
5090         info = mono_get_array_new_va_icall (rank);
5091
5092         cfg->flags |= MONO_CFG_HAS_VARARGS;
5093
5094         /* mono_array_new_va () needs a vararg calling convention */
5095         cfg->disable_llvm = TRUE;
5096
5097         /* FIXME: This uses info->sig, but it should use the signature of the wrapper */
5098         return mono_emit_native_call (cfg, mono_icall_get_wrapper (info), info->sig, sp);
5099 }
5100
5101 /*
5102  * handle_constrained_gsharedvt_call:
5103  *
5104  *   Handle constrained calls where the receiver is a gsharedvt type.
5105  * Return the instruction representing the call. Set the cfg exception on failure.
5106  */
5107 static MonoInst*
5108 handle_constrained_gsharedvt_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **sp, MonoClass *constrained_class,
5109                                                                    gboolean *ref_emit_widen)
5110 {
5111         MonoInst *ins = NULL;
5112         gboolean emit_widen = *ref_emit_widen;
5113
5114         /*
5115          * Constrained calls need to behave differently at runtime dependending on whenever the receiver is instantiated as ref type or as a vtype.
5116          * This is hard to do with the current call code, since we would have to emit a branch and two different calls. So instead, we
5117          * pack the arguments into an array, and do the rest of the work in in an icall.
5118          */
5119         if (((cmethod->klass == mono_defaults.object_class) || (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE) || (!cmethod->klass->valuetype && cmethod->klass->image != mono_defaults.corlib)) &&
5120                 (MONO_TYPE_IS_VOID (fsig->ret) || MONO_TYPE_IS_PRIMITIVE (fsig->ret) || MONO_TYPE_IS_REFERENCE (fsig->ret) || MONO_TYPE_ISSTRUCT (fsig->ret) || mini_is_gsharedvt_type (fsig->ret)) &&
5121                 (fsig->param_count == 0 || (!fsig->hasthis && fsig->param_count == 1) || (fsig->param_count == 1 && (MONO_TYPE_IS_REFERENCE (fsig->params [0]) || fsig->params [0]->byref || mini_is_gsharedvt_type (fsig->params [0]))))) {
5122                 MonoInst *args [16];
5123
5124                 /*
5125                  * This case handles calls to
5126                  * - object:ToString()/Equals()/GetHashCode(),
5127                  * - System.IComparable<T>:CompareTo()
5128                  * - System.IEquatable<T>:Equals ()
5129                  * plus some simple interface calls enough to support AsyncTaskMethodBuilder.
5130                  */
5131
5132                 args [0] = sp [0];
5133                 if (mono_method_check_context_used (cmethod))
5134                         args [1] = emit_get_rgctx_method (cfg, mono_method_check_context_used (cmethod), cmethod, MONO_RGCTX_INFO_METHOD);
5135                 else
5136                         EMIT_NEW_METHODCONST (cfg, args [1], cmethod);
5137                 args [2] = emit_get_rgctx_klass (cfg, mono_class_check_context_used (constrained_class), constrained_class, MONO_RGCTX_INFO_KLASS);
5138
5139                 /* !fsig->hasthis is for the wrapper for the Object.GetType () icall */
5140                 if (fsig->hasthis && fsig->param_count) {
5141                         /* Pass the arguments using a localloc-ed array using the format expected by runtime_invoke () */
5142                         MONO_INST_NEW (cfg, ins, OP_LOCALLOC_IMM);
5143                         ins->dreg = alloc_preg (cfg);
5144                         ins->inst_imm = fsig->param_count * sizeof (mgreg_t);
5145                         MONO_ADD_INS (cfg->cbb, ins);
5146                         args [4] = ins;
5147
5148                         if (mini_is_gsharedvt_type (fsig->params [0])) {
5149                                 int addr_reg;
5150
5151                                 args [3] = emit_get_gsharedvt_info_klass (cfg, mono_class_from_mono_type (fsig->params [0]), MONO_RGCTX_INFO_CLASS_BOX_TYPE);
5152
5153                                 EMIT_NEW_VARLOADA_VREG (cfg, ins, sp [1]->dreg, fsig->params [0]);
5154                                 addr_reg = ins->dreg;
5155                                 EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, args [4]->dreg, 0, addr_reg);
5156                         } else {
5157                                 EMIT_NEW_ICONST (cfg, args [3], 0);
5158                                 EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, args [4]->dreg, 0, sp [1]->dreg);
5159                         }
5160                 } else {
5161                         EMIT_NEW_ICONST (cfg, args [3], 0);
5162                         EMIT_NEW_ICONST (cfg, args [4], 0);
5163                 }
5164                 ins = mono_emit_jit_icall (cfg, mono_gsharedvt_constrained_call, args);
5165                 emit_widen = FALSE;
5166
5167                 if (mini_is_gsharedvt_type (fsig->ret)) {
5168                         ins = handle_unbox_gsharedvt (cfg, mono_class_from_mono_type (fsig->ret), ins);
5169                 } else if (MONO_TYPE_IS_PRIMITIVE (fsig->ret) || MONO_TYPE_ISSTRUCT (fsig->ret)) {
5170                         MonoInst *add;
5171
5172                         /* Unbox */
5173                         NEW_BIALU_IMM (cfg, add, OP_ADD_IMM, alloc_dreg (cfg, STACK_MP), ins->dreg, sizeof (MonoObject));
5174                         MONO_ADD_INS (cfg->cbb, add);
5175                         /* Load value */
5176                         NEW_LOAD_MEMBASE_TYPE (cfg, ins, fsig->ret, add->dreg, 0);
5177                         MONO_ADD_INS (cfg->cbb, ins);
5178                         /* ins represents the call result */
5179                 }
5180         } else {
5181                 GSHAREDVT_FAILURE (CEE_CALLVIRT);
5182         }
5183
5184         *ref_emit_widen = emit_widen;
5185
5186         return ins;
5187
5188  exception_exit:
5189         return NULL;
5190 }
5191
5192 static void
5193 mono_emit_load_got_addr (MonoCompile *cfg)
5194 {
5195         MonoInst *getaddr, *dummy_use;
5196
5197         if (!cfg->got_var || cfg->got_var_allocated)
5198                 return;
5199
5200         MONO_INST_NEW (cfg, getaddr, OP_LOAD_GOTADDR);
5201         getaddr->cil_code = cfg->header->code;
5202         getaddr->dreg = cfg->got_var->dreg;
5203
5204         /* Add it to the start of the first bblock */
5205         if (cfg->bb_entry->code) {
5206                 getaddr->next = cfg->bb_entry->code;
5207                 cfg->bb_entry->code = getaddr;
5208         }
5209         else
5210                 MONO_ADD_INS (cfg->bb_entry, getaddr);
5211
5212         cfg->got_var_allocated = TRUE;
5213
5214         /* 
5215          * Add a dummy use to keep the got_var alive, since real uses might
5216          * only be generated by the back ends.
5217          * Add it to end_bblock, so the variable's lifetime covers the whole
5218          * method.
5219          * It would be better to make the usage of the got var explicit in all
5220          * cases when the backend needs it (i.e. calls, throw etc.), so this
5221          * wouldn't be needed.
5222          */
5223         NEW_DUMMY_USE (cfg, dummy_use, cfg->got_var);
5224         MONO_ADD_INS (cfg->bb_exit, dummy_use);
5225 }
5226
5227 static int inline_limit;
5228 static gboolean inline_limit_inited;
5229
5230 static gboolean
5231 mono_method_check_inlining (MonoCompile *cfg, MonoMethod *method)
5232 {
5233         MonoMethodHeaderSummary header;
5234         MonoVTable *vtable;
5235 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
5236         MonoMethodSignature *sig = mono_method_signature (method);
5237         int i;
5238 #endif
5239
5240         if (cfg->disable_inline)
5241                 return FALSE;
5242         if (cfg->gshared)
5243                 return FALSE;
5244
5245         if (cfg->inline_depth > 10)
5246                 return FALSE;
5247
5248         if (!mono_method_get_header_summary (method, &header))
5249                 return FALSE;
5250
5251         /*runtime, icall and pinvoke are checked by summary call*/
5252         if ((method->iflags & METHOD_IMPL_ATTRIBUTE_NOINLINING) ||
5253             (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) ||
5254             (mono_class_is_marshalbyref (method->klass)) ||
5255             header.has_clauses)
5256                 return FALSE;
5257
5258         /* also consider num_locals? */
5259         /* Do the size check early to avoid creating vtables */
5260         if (!inline_limit_inited) {
5261                 if (g_getenv ("MONO_INLINELIMIT"))
5262                         inline_limit = atoi (g_getenv ("MONO_INLINELIMIT"));
5263                 else
5264                         inline_limit = INLINE_LENGTH_LIMIT;
5265                 inline_limit_inited = TRUE;
5266         }
5267         if (header.code_size >= inline_limit && !(method->iflags & METHOD_IMPL_ATTRIBUTE_AGGRESSIVE_INLINING))
5268                 return FALSE;
5269
5270         /*
5271          * if we can initialize the class of the method right away, we do,
5272          * otherwise we don't allow inlining if the class needs initialization,
5273          * since it would mean inserting a call to mono_runtime_class_init()
5274          * inside the inlined code
5275          */
5276         if (!(cfg->opt & MONO_OPT_SHARED)) {
5277                 /* The AggressiveInlining hint is a good excuse to force that cctor to run. */
5278                 if (method->iflags & METHOD_IMPL_ATTRIBUTE_AGGRESSIVE_INLINING) {
5279                         vtable = mono_class_vtable (cfg->domain, method->klass);
5280                         if (!vtable)
5281                                 return FALSE;
5282                         if (!cfg->compile_aot)
5283                                 mono_runtime_class_init (vtable);
5284                 } else if (method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT) {
5285                         if (cfg->run_cctors && method->klass->has_cctor) {
5286                                 /*FIXME it would easier and lazier to just use mono_class_try_get_vtable */
5287                                 if (!method->klass->runtime_info)
5288                                         /* No vtable created yet */
5289                                         return FALSE;
5290                                 vtable = mono_class_vtable (cfg->domain, method->klass);
5291                                 if (!vtable)
5292                                         return FALSE;
5293                                 /* This makes so that inline cannot trigger */
5294                                 /* .cctors: too many apps depend on them */
5295                                 /* running with a specific order... */
5296                                 if (! vtable->initialized)
5297                                         return FALSE;
5298                                 mono_runtime_class_init (vtable);
5299                         }
5300                 } else if (mono_class_needs_cctor_run (method->klass, NULL)) {
5301                         if (!method->klass->runtime_info)
5302                                 /* No vtable created yet */
5303                                 return FALSE;
5304                         vtable = mono_class_vtable (cfg->domain, method->klass);
5305                         if (!vtable)
5306                                 return FALSE;
5307                         if (!vtable->initialized)
5308                                 return FALSE;
5309                 }
5310         } else {
5311                 /* 
5312                  * If we're compiling for shared code
5313                  * the cctor will need to be run at aot method load time, for example,
5314                  * or at the end of the compilation of the inlining method.
5315                  */
5316                 if (mono_class_needs_cctor_run (method->klass, NULL) && !((method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)))
5317                         return FALSE;
5318         }
5319
5320 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
5321         if (mono_arch_is_soft_float ()) {
5322                 /* FIXME: */
5323                 if (sig->ret && sig->ret->type == MONO_TYPE_R4)
5324                         return FALSE;
5325                 for (i = 0; i < sig->param_count; ++i)
5326                         if (!sig->params [i]->byref && sig->params [i]->type == MONO_TYPE_R4)
5327                                 return FALSE;
5328         }
5329 #endif
5330
5331         if (g_list_find (cfg->dont_inline, method))
5332                 return FALSE;
5333
5334         return TRUE;
5335 }
5336
5337 static gboolean
5338 mini_field_access_needs_cctor_run (MonoCompile *cfg, MonoMethod *method, MonoClass *klass, MonoVTable *vtable)
5339 {
5340         if (!cfg->compile_aot) {
5341                 g_assert (vtable);
5342                 if (vtable->initialized)
5343                         return FALSE;
5344         }
5345
5346         if (klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT) {
5347                 if (cfg->method == method)
5348                         return FALSE;
5349         }
5350
5351         if (!mono_class_needs_cctor_run (klass, method))
5352                 return FALSE;
5353
5354         if (! (method->flags & METHOD_ATTRIBUTE_STATIC) && (klass == method->klass))
5355                 /* The initialization is already done before the method is called */
5356                 return FALSE;
5357
5358         return TRUE;
5359 }
5360
5361 static MonoInst*
5362 mini_emit_ldelema_1_ins (MonoCompile *cfg, MonoClass *klass, MonoInst *arr, MonoInst *index, gboolean bcheck)
5363 {
5364         MonoInst *ins;
5365         guint32 size;
5366         int mult_reg, add_reg, array_reg, index_reg, index2_reg;
5367         int context_used;
5368
5369         if (mini_is_gsharedvt_variable_klass (klass)) {
5370                 size = -1;
5371         } else {
5372                 mono_class_init (klass);
5373                 size = mono_class_array_element_size (klass);
5374         }
5375
5376         mult_reg = alloc_preg (cfg);
5377         array_reg = arr->dreg;
5378         index_reg = index->dreg;
5379
5380 #if SIZEOF_REGISTER == 8
5381         /* The array reg is 64 bits but the index reg is only 32 */
5382         if (COMPILE_LLVM (cfg)) {
5383                 /* Not needed */
5384                 index2_reg = index_reg;
5385         } else {
5386                 index2_reg = alloc_preg (cfg);
5387                 MONO_EMIT_NEW_UNALU (cfg, OP_SEXT_I4, index2_reg, index_reg);
5388         }
5389 #else
5390         if (index->type == STACK_I8) {
5391                 index2_reg = alloc_preg (cfg);
5392                 MONO_EMIT_NEW_UNALU (cfg, OP_LCONV_TO_I4, index2_reg, index_reg);
5393         } else {
5394                 index2_reg = index_reg;
5395         }
5396 #endif
5397
5398         if (bcheck)
5399                 MONO_EMIT_BOUNDS_CHECK (cfg, array_reg, MonoArray, max_length, index2_reg);
5400
5401 #if defined(TARGET_X86) || defined(TARGET_AMD64)
5402         if (size == 1 || size == 2 || size == 4 || size == 8) {
5403                 static const int fast_log2 [] = { 1, 0, 1, -1, 2, -1, -1, -1, 3 };
5404
5405                 EMIT_NEW_X86_LEA (cfg, ins, array_reg, index2_reg, fast_log2 [size], MONO_STRUCT_OFFSET (MonoArray, vector));
5406                 ins->klass = mono_class_get_element_class (klass);
5407                 ins->type = STACK_MP;
5408
5409                 return ins;
5410         }
5411 #endif          
5412
5413         add_reg = alloc_ireg_mp (cfg);
5414
5415         if (size == -1) {
5416                 MonoInst *rgctx_ins;
5417
5418                 /* gsharedvt */
5419                 g_assert (cfg->gshared);
5420                 context_used = mini_class_check_context_used (cfg, klass);
5421                 g_assert (context_used);
5422                 rgctx_ins = emit_get_gsharedvt_info_klass (cfg, klass, MONO_RGCTX_INFO_ARRAY_ELEMENT_SIZE);
5423                 MONO_EMIT_NEW_BIALU (cfg, OP_IMUL, mult_reg, index2_reg, rgctx_ins->dreg);
5424         } else {
5425                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_MUL_IMM, mult_reg, index2_reg, size);
5426         }
5427         MONO_EMIT_NEW_BIALU (cfg, OP_PADD, add_reg, array_reg, mult_reg);
5428         NEW_BIALU_IMM (cfg, ins, OP_PADD_IMM, add_reg, add_reg, MONO_STRUCT_OFFSET (MonoArray, vector));
5429         ins->klass = mono_class_get_element_class (klass);
5430         ins->type = STACK_MP;
5431         MONO_ADD_INS (cfg->cbb, ins);
5432
5433         return ins;
5434 }
5435
5436 static MonoInst*
5437 mini_emit_ldelema_2_ins (MonoCompile *cfg, MonoClass *klass, MonoInst *arr, MonoInst *index_ins1, MonoInst *index_ins2)
5438 {
5439         int bounds_reg = alloc_preg (cfg);
5440         int add_reg = alloc_ireg_mp (cfg);
5441         int mult_reg = alloc_preg (cfg);
5442         int mult2_reg = alloc_preg (cfg);
5443         int low1_reg = alloc_preg (cfg);
5444         int low2_reg = alloc_preg (cfg);
5445         int high1_reg = alloc_preg (cfg);
5446         int high2_reg = alloc_preg (cfg);
5447         int realidx1_reg = alloc_preg (cfg);
5448         int realidx2_reg = alloc_preg (cfg);
5449         int sum_reg = alloc_preg (cfg);
5450         int index1, index2, tmpreg;
5451         MonoInst *ins;
5452         guint32 size;
5453
5454         mono_class_init (klass);
5455         size = mono_class_array_element_size (klass);
5456
5457         index1 = index_ins1->dreg;
5458         index2 = index_ins2->dreg;
5459
5460 #if SIZEOF_REGISTER == 8
5461         /* The array reg is 64 bits but the index reg is only 32 */
5462         if (COMPILE_LLVM (cfg)) {
5463                 /* Not needed */
5464         } else {
5465                 tmpreg = alloc_preg (cfg);
5466                 MONO_EMIT_NEW_UNALU (cfg, OP_SEXT_I4, tmpreg, index1);
5467                 index1 = tmpreg;
5468                 tmpreg = alloc_preg (cfg);
5469                 MONO_EMIT_NEW_UNALU (cfg, OP_SEXT_I4, tmpreg, index2);
5470                 index2 = tmpreg;
5471         }
5472 #else
5473         // FIXME: Do we need to do something here for i8 indexes, like in ldelema_1_ins ?
5474         tmpreg = -1;
5475 #endif
5476
5477         /* range checking */
5478         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, bounds_reg, 
5479                                        arr->dreg, MONO_STRUCT_OFFSET (MonoArray, bounds));
5480
5481         MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, low1_reg, 
5482                                        bounds_reg, MONO_STRUCT_OFFSET (MonoArrayBounds, lower_bound));
5483         MONO_EMIT_NEW_BIALU (cfg, OP_PSUB, realidx1_reg, index1, low1_reg);
5484         MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, high1_reg, 
5485                                        bounds_reg, MONO_STRUCT_OFFSET (MonoArrayBounds, length));
5486         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, high1_reg, realidx1_reg);
5487         MONO_EMIT_NEW_COND_EXC (cfg, LE_UN, "IndexOutOfRangeException");
5488
5489         MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, low2_reg, 
5490                                        bounds_reg, sizeof (MonoArrayBounds) + MONO_STRUCT_OFFSET (MonoArrayBounds, lower_bound));
5491         MONO_EMIT_NEW_BIALU (cfg, OP_PSUB, realidx2_reg, index2, low2_reg);
5492         MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, high2_reg, 
5493                                        bounds_reg, sizeof (MonoArrayBounds) + MONO_STRUCT_OFFSET (MonoArrayBounds, length));
5494         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, high2_reg, realidx2_reg);
5495         MONO_EMIT_NEW_COND_EXC (cfg, LE_UN, "IndexOutOfRangeException");
5496
5497         MONO_EMIT_NEW_BIALU (cfg, OP_PMUL, mult_reg, high2_reg, realidx1_reg);
5498         MONO_EMIT_NEW_BIALU (cfg, OP_PADD, sum_reg, mult_reg, realidx2_reg);
5499         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_PMUL_IMM, mult2_reg, sum_reg, size);
5500         MONO_EMIT_NEW_BIALU (cfg, OP_PADD, add_reg, mult2_reg, arr->dreg);
5501         NEW_BIALU_IMM (cfg, ins, OP_PADD_IMM, add_reg, add_reg, MONO_STRUCT_OFFSET (MonoArray, vector));
5502
5503         ins->type = STACK_MP;
5504         ins->klass = klass;
5505         MONO_ADD_INS (cfg->cbb, ins);
5506
5507         return ins;
5508 }
5509
5510 static MonoInst*
5511 mini_emit_ldelema_ins (MonoCompile *cfg, MonoMethod *cmethod, MonoInst **sp, unsigned char *ip, gboolean is_set)
5512 {
5513         int rank;
5514         MonoInst *addr;
5515         MonoMethod *addr_method;
5516         int element_size;
5517         MonoClass *eclass = cmethod->klass->element_class;
5518
5519         rank = mono_method_signature (cmethod)->param_count - (is_set? 1: 0);
5520
5521         if (rank == 1)
5522                 return mini_emit_ldelema_1_ins (cfg, eclass, sp [0], sp [1], TRUE);
5523
5524         /* emit_ldelema_2 depends on OP_LMUL */
5525         if (!cfg->backend->emulate_mul_div && rank == 2 && (cfg->opt & MONO_OPT_INTRINS) && !mini_is_gsharedvt_variable_klass (eclass)) {
5526                 return mini_emit_ldelema_2_ins (cfg, eclass, sp [0], sp [1], sp [2]);
5527         }
5528
5529         if (mini_is_gsharedvt_variable_klass (eclass))
5530                 element_size = 0;
5531         else
5532                 element_size = mono_class_array_element_size (eclass);
5533         addr_method = mono_marshal_get_array_address (rank, element_size);
5534         addr = mono_emit_method_call (cfg, addr_method, sp, NULL);
5535
5536         return addr;
5537 }
5538
5539 static MonoBreakPolicy
5540 always_insert_breakpoint (MonoMethod *method)
5541 {
5542         return MONO_BREAK_POLICY_ALWAYS;
5543 }
5544
5545 static MonoBreakPolicyFunc break_policy_func = always_insert_breakpoint;
5546
5547 /**
5548  * mono_set_break_policy:
5549  * policy_callback: the new callback function
5550  *
5551  * Allow embedders to decide wherther to actually obey breakpoint instructions
5552  * (both break IL instructions and Debugger.Break () method calls), for example
5553  * to not allow an app to be aborted by a perfectly valid IL opcode when executing
5554  * untrusted or semi-trusted code.
5555  *
5556  * @policy_callback will be called every time a break point instruction needs to
5557  * be inserted with the method argument being the method that calls Debugger.Break()
5558  * or has the IL break instruction. The callback should return #MONO_BREAK_POLICY_NEVER
5559  * if it wants the breakpoint to not be effective in the given method.
5560  * #MONO_BREAK_POLICY_ALWAYS is the default.
5561  */
5562 void
5563 mono_set_break_policy (MonoBreakPolicyFunc policy_callback)
5564 {
5565         if (policy_callback)
5566                 break_policy_func = policy_callback;
5567         else
5568                 break_policy_func = always_insert_breakpoint;
5569 }
5570
5571 static gboolean
5572 should_insert_brekpoint (MonoMethod *method) {
5573         switch (break_policy_func (method)) {
5574         case MONO_BREAK_POLICY_ALWAYS:
5575                 return TRUE;
5576         case MONO_BREAK_POLICY_NEVER:
5577                 return FALSE;
5578         case MONO_BREAK_POLICY_ON_DBG:
5579                 g_warning ("mdb no longer supported");
5580                 return FALSE;
5581         default:
5582                 g_warning ("Incorrect value returned from break policy callback");
5583                 return FALSE;
5584         }
5585 }
5586
5587 /* optimize the simple GetGenericValueImpl/SetGenericValueImpl generic icalls */
5588 static MonoInst*
5589 emit_array_generic_access (MonoCompile *cfg, MonoMethodSignature *fsig, MonoInst **args, int is_set)
5590 {
5591         MonoInst *addr, *store, *load;
5592         MonoClass *eklass = mono_class_from_mono_type (fsig->params [2]);
5593
5594         /* the bounds check is already done by the callers */
5595         addr = mini_emit_ldelema_1_ins (cfg, eklass, args [0], args [1], FALSE);
5596         if (is_set) {
5597                 EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, load, &eklass->byval_arg, args [2]->dreg, 0);
5598                 EMIT_NEW_STORE_MEMBASE_TYPE (cfg, store, &eklass->byval_arg, addr->dreg, 0, load->dreg);
5599                 if (mini_type_is_reference (fsig->params [2]))
5600                         emit_write_barrier (cfg, addr, load);
5601         } else {
5602                 EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, load, &eklass->byval_arg, addr->dreg, 0);
5603                 EMIT_NEW_STORE_MEMBASE_TYPE (cfg, store, &eklass->byval_arg, args [2]->dreg, 0, load->dreg);
5604         }
5605         return store;
5606 }
5607
5608
5609 static gboolean
5610 generic_class_is_reference_type (MonoCompile *cfg, MonoClass *klass)
5611 {
5612         return mini_type_is_reference (&klass->byval_arg);
5613 }
5614
5615 static MonoInst*
5616 emit_array_store (MonoCompile *cfg, MonoClass *klass, MonoInst **sp, gboolean safety_checks)
5617 {
5618         if (safety_checks && generic_class_is_reference_type (cfg, klass) &&
5619                 !(sp [2]->opcode == OP_PCONST && sp [2]->inst_p0 == NULL)) {
5620                 MonoClass *obj_array = mono_array_class_get_cached (mono_defaults.object_class, 1);
5621                 MonoMethod *helper = mono_marshal_get_virtual_stelemref (obj_array);
5622                 MonoInst *iargs [3];
5623
5624                 if (!helper->slot)
5625                         mono_class_setup_vtable (obj_array);
5626                 g_assert (helper->slot);
5627
5628                 if (sp [0]->type != STACK_OBJ)
5629                         return NULL;
5630                 if (sp [2]->type != STACK_OBJ)
5631                         return NULL;
5632
5633                 iargs [2] = sp [2];
5634                 iargs [1] = sp [1];
5635                 iargs [0] = sp [0];
5636
5637                 return mono_emit_method_call (cfg, helper, iargs, sp [0]);
5638         } else {
5639                 MonoInst *ins;
5640
5641                 if (mini_is_gsharedvt_variable_klass (klass)) {
5642                         MonoInst *addr;
5643
5644                         // FIXME-VT: OP_ICONST optimization
5645                         addr = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], TRUE);
5646                         EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, addr->dreg, 0, sp [2]->dreg);
5647                         ins->opcode = OP_STOREV_MEMBASE;
5648                 } else if (sp [1]->opcode == OP_ICONST) {
5649                         int array_reg = sp [0]->dreg;
5650                         int index_reg = sp [1]->dreg;
5651                         int offset = (mono_class_array_element_size (klass) * sp [1]->inst_c0) + MONO_STRUCT_OFFSET (MonoArray, vector);
5652
5653                         if (safety_checks)
5654                                 MONO_EMIT_BOUNDS_CHECK (cfg, array_reg, MonoArray, max_length, index_reg);
5655                         EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, array_reg, offset, sp [2]->dreg);
5656                 } else {
5657                         MonoInst *addr = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], safety_checks);
5658                         EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, addr->dreg, 0, sp [2]->dreg);
5659                         if (generic_class_is_reference_type (cfg, klass))
5660                                 emit_write_barrier (cfg, addr, sp [2]);
5661                 }
5662                 return ins;
5663         }
5664 }
5665
5666 static MonoInst*
5667 emit_array_unsafe_access (MonoCompile *cfg, MonoMethodSignature *fsig, MonoInst **args, int is_set)
5668 {
5669         MonoClass *eklass;
5670         
5671         if (is_set)
5672                 eklass = mono_class_from_mono_type (fsig->params [2]);
5673         else
5674                 eklass = mono_class_from_mono_type (fsig->ret);
5675
5676         if (is_set) {
5677                 return emit_array_store (cfg, eklass, args, FALSE);
5678         } else {
5679                 MonoInst *ins, *addr = mini_emit_ldelema_1_ins (cfg, eklass, args [0], args [1], FALSE);
5680                 EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &eklass->byval_arg, addr->dreg, 0);
5681                 return ins;
5682         }
5683 }
5684
5685 static gboolean
5686 is_unsafe_mov_compatible (MonoCompile *cfg, MonoClass *param_klass, MonoClass *return_klass)
5687 {
5688         uint32_t align;
5689
5690         param_klass = mono_class_from_mono_type (mini_get_underlying_type (&param_klass->byval_arg));
5691
5692         //Only allow for valuetypes
5693         if (!param_klass->valuetype || !return_klass->valuetype)
5694                 return FALSE;
5695
5696         //That are blitable
5697         if (param_klass->has_references || return_klass->has_references)
5698                 return FALSE;
5699
5700         /* Avoid mixing structs and primitive types/enums, they need to be handled differently in the JIT */
5701         if ((MONO_TYPE_ISSTRUCT (&param_klass->byval_arg) && !MONO_TYPE_ISSTRUCT (&return_klass->byval_arg)) ||
5702                 (!MONO_TYPE_ISSTRUCT (&param_klass->byval_arg) && MONO_TYPE_ISSTRUCT (&return_klass->byval_arg)))
5703                 return FALSE;
5704
5705         if (param_klass->byval_arg.type == MONO_TYPE_R4 || param_klass->byval_arg.type == MONO_TYPE_R8 ||
5706                 return_klass->byval_arg.type == MONO_TYPE_R4 || return_klass->byval_arg.type == MONO_TYPE_R8)
5707                 return FALSE;
5708
5709         //And have the same size
5710         if (mono_class_value_size (param_klass, &align) != mono_class_value_size (return_klass, &align))
5711                 return FALSE;
5712         return TRUE;
5713 }
5714
5715 static MonoInst*
5716 emit_array_unsafe_mov (MonoCompile *cfg, MonoMethodSignature *fsig, MonoInst **args)
5717 {
5718         MonoClass *param_klass = mono_class_from_mono_type (fsig->params [0]);
5719         MonoClass *return_klass = mono_class_from_mono_type (fsig->ret);
5720
5721         //Valuetypes that are semantically equivalent
5722         if (is_unsafe_mov_compatible (cfg, param_klass, return_klass))
5723                 return args [0];
5724
5725         //Arrays of valuetypes that are semantically equivalent
5726         if (param_klass->rank == 1 && return_klass->rank == 1 && is_unsafe_mov_compatible (cfg, param_klass->element_class, return_klass->element_class))
5727                 return args [0];
5728
5729         return NULL;
5730 }
5731
5732 static MonoInst*
5733 mini_emit_inst_for_ctor (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
5734 {
5735 #ifdef MONO_ARCH_SIMD_INTRINSICS
5736         MonoInst *ins = NULL;
5737
5738         if (cfg->opt & MONO_OPT_SIMD) {
5739                 ins = mono_emit_simd_intrinsics (cfg, cmethod, fsig, args);
5740                 if (ins)
5741                         return ins;
5742         }
5743 #endif
5744
5745         return mono_emit_native_types_intrinsics (cfg, cmethod, fsig, args);
5746 }
5747
5748 static MonoInst*
5749 emit_memory_barrier (MonoCompile *cfg, int kind)
5750 {
5751         MonoInst *ins = NULL;
5752         MONO_INST_NEW (cfg, ins, OP_MEMORY_BARRIER);
5753         MONO_ADD_INS (cfg->cbb, ins);
5754         ins->backend.memory_barrier_kind = kind;
5755
5756         return ins;
5757 }
5758
5759 static MonoInst*
5760 llvm_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
5761 {
5762         MonoInst *ins = NULL;
5763         int opcode = 0;
5764
5765         /* The LLVM backend supports these intrinsics */
5766         if (cmethod->klass == mono_defaults.math_class) {
5767                 if (strcmp (cmethod->name, "Sin") == 0) {
5768                         opcode = OP_SIN;
5769                 } else if (strcmp (cmethod->name, "Cos") == 0) {
5770                         opcode = OP_COS;
5771                 } else if (strcmp (cmethod->name, "Sqrt") == 0) {
5772                         opcode = OP_SQRT;
5773                 } else if (strcmp (cmethod->name, "Abs") == 0 && fsig->params [0]->type == MONO_TYPE_R8) {
5774                         opcode = OP_ABS;
5775                 }
5776
5777                 if (opcode && fsig->param_count == 1) {
5778                         MONO_INST_NEW (cfg, ins, opcode);
5779                         ins->type = STACK_R8;
5780                         ins->dreg = mono_alloc_freg (cfg);
5781                         ins->sreg1 = args [0]->dreg;
5782                         MONO_ADD_INS (cfg->cbb, ins);
5783                 }
5784
5785                 opcode = 0;
5786                 if (cfg->opt & MONO_OPT_CMOV) {
5787                         if (strcmp (cmethod->name, "Min") == 0) {
5788                                 if (fsig->params [0]->type == MONO_TYPE_I4)
5789                                         opcode = OP_IMIN;
5790                                 if (fsig->params [0]->type == MONO_TYPE_U4)
5791                                         opcode = OP_IMIN_UN;
5792                                 else if (fsig->params [0]->type == MONO_TYPE_I8)
5793                                         opcode = OP_LMIN;
5794                                 else if (fsig->params [0]->type == MONO_TYPE_U8)
5795                                         opcode = OP_LMIN_UN;
5796                         } else if (strcmp (cmethod->name, "Max") == 0) {
5797                                 if (fsig->params [0]->type == MONO_TYPE_I4)
5798                                         opcode = OP_IMAX;
5799                                 if (fsig->params [0]->type == MONO_TYPE_U4)
5800                                         opcode = OP_IMAX_UN;
5801                                 else if (fsig->params [0]->type == MONO_TYPE_I8)
5802                                         opcode = OP_LMAX;
5803                                 else if (fsig->params [0]->type == MONO_TYPE_U8)
5804                                         opcode = OP_LMAX_UN;
5805                         }
5806                 }
5807
5808                 if (opcode && fsig->param_count == 2) {
5809                         MONO_INST_NEW (cfg, ins, opcode);
5810                         ins->type = fsig->params [0]->type == MONO_TYPE_I4 ? STACK_I4 : STACK_I8;
5811                         ins->dreg = mono_alloc_ireg (cfg);
5812                         ins->sreg1 = args [0]->dreg;
5813                         ins->sreg2 = args [1]->dreg;
5814                         MONO_ADD_INS (cfg->cbb, ins);
5815                 }
5816         }
5817
5818         return ins;
5819 }
5820
5821 static MonoInst*
5822 mini_emit_inst_for_sharable_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
5823 {
5824         if (cmethod->klass == mono_defaults.array_class) {
5825                 if (strcmp (cmethod->name, "UnsafeStore") == 0)
5826                         return emit_array_unsafe_access (cfg, fsig, args, TRUE);
5827                 else if (strcmp (cmethod->name, "UnsafeLoad") == 0)
5828                         return emit_array_unsafe_access (cfg, fsig, args, FALSE);
5829                 else if (strcmp (cmethod->name, "UnsafeMov") == 0)
5830                         return emit_array_unsafe_mov (cfg, fsig, args);
5831         }
5832
5833         return NULL;
5834 }
5835
5836 static MonoInst*
5837 mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
5838 {
5839         MonoInst *ins = NULL;
5840
5841         static MonoClass *runtime_helpers_class = NULL;
5842         if (! runtime_helpers_class)
5843                 runtime_helpers_class = mono_class_from_name (mono_defaults.corlib,
5844                         "System.Runtime.CompilerServices", "RuntimeHelpers");
5845
5846         if (cmethod->klass == mono_defaults.string_class) {
5847                 if (strcmp (cmethod->name, "get_Chars") == 0 && fsig->param_count + fsig->hasthis == 2) {
5848                         int dreg = alloc_ireg (cfg);
5849                         int index_reg = alloc_preg (cfg);
5850                         int add_reg = alloc_preg (cfg);
5851
5852 #if SIZEOF_REGISTER == 8
5853                         /* The array reg is 64 bits but the index reg is only 32 */
5854                         MONO_EMIT_NEW_UNALU (cfg, OP_SEXT_I4, index_reg, args [1]->dreg);
5855 #else
5856                         index_reg = args [1]->dreg;
5857 #endif  
5858                         MONO_EMIT_BOUNDS_CHECK (cfg, args [0]->dreg, MonoString, length, index_reg);
5859
5860 #if defined(TARGET_X86) || defined(TARGET_AMD64)
5861                         EMIT_NEW_X86_LEA (cfg, ins, args [0]->dreg, index_reg, 1, MONO_STRUCT_OFFSET (MonoString, chars));
5862                         add_reg = ins->dreg;
5863                         EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOADU2_MEMBASE, dreg, 
5864                                                                    add_reg, 0);
5865 #else
5866                         int mult_reg = alloc_preg (cfg);
5867                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHL_IMM, mult_reg, index_reg, 1);
5868                         MONO_EMIT_NEW_BIALU (cfg, OP_PADD, add_reg, mult_reg, args [0]->dreg);
5869                         EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOADU2_MEMBASE, dreg, 
5870                                                                    add_reg, MONO_STRUCT_OFFSET (MonoString, chars));
5871 #endif
5872                         type_from_op (cfg, ins, NULL, NULL);
5873                         return ins;
5874                 } else if (strcmp (cmethod->name, "get_Length") == 0 && fsig->param_count + fsig->hasthis == 1) {
5875                         int dreg = alloc_ireg (cfg);
5876                         /* Decompose later to allow more optimizations */
5877                         EMIT_NEW_UNALU (cfg, ins, OP_STRLEN, dreg, args [0]->dreg);
5878                         ins->type = STACK_I4;
5879                         ins->flags |= MONO_INST_FAULT;
5880                         cfg->cbb->has_array_access = TRUE;
5881                         cfg->flags |= MONO_CFG_HAS_ARRAY_ACCESS;
5882
5883                         return ins;
5884                 } else 
5885                         return NULL;
5886         } else if (cmethod->klass == mono_defaults.object_class) {
5887
5888                 if (strcmp (cmethod->name, "GetType") == 0 && fsig->param_count + fsig->hasthis == 1) {
5889                         int dreg = alloc_ireg_ref (cfg);
5890                         int vt_reg = alloc_preg (cfg);
5891                         MONO_EMIT_NEW_LOAD_MEMBASE_FAULT (cfg, vt_reg, args [0]->dreg, MONO_STRUCT_OFFSET (MonoObject, vtable));
5892                         EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, dreg, vt_reg, MONO_STRUCT_OFFSET (MonoVTable, type));
5893                         type_from_op (cfg, ins, NULL, NULL);
5894
5895                         return ins;
5896                 } else if (!cfg->backend->emulate_mul_div && strcmp (cmethod->name, "InternalGetHashCode") == 0 && fsig->param_count == 1 && !mono_gc_is_moving ()) {
5897                         int dreg = alloc_ireg (cfg);
5898                         int t1 = alloc_ireg (cfg);
5899         
5900                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHL_IMM, t1, args [0]->dreg, 3);
5901                         EMIT_NEW_BIALU_IMM (cfg, ins, OP_MUL_IMM, dreg, t1, 2654435761u);
5902                         ins->type = STACK_I4;
5903
5904                         return ins;
5905                 } else if (strcmp (cmethod->name, ".ctor") == 0 && fsig->param_count == 0) {
5906                         MONO_INST_NEW (cfg, ins, OP_NOP);
5907                         MONO_ADD_INS (cfg->cbb, ins);
5908                         return ins;
5909                 } else
5910                         return NULL;
5911         } else if (cmethod->klass == mono_defaults.array_class) {
5912                 if (strcmp (cmethod->name, "GetGenericValueImpl") == 0 && fsig->param_count + fsig->hasthis == 3 && !cfg->gsharedvt)
5913                         return emit_array_generic_access (cfg, fsig, args, FALSE);
5914                 else if (strcmp (cmethod->name, "SetGenericValueImpl") == 0 && fsig->param_count + fsig->hasthis == 3 && !cfg->gsharedvt)
5915                         return emit_array_generic_access (cfg, fsig, args, TRUE);
5916
5917 #ifndef MONO_BIG_ARRAYS
5918                 /*
5919                  * This is an inline version of GetLength/GetLowerBound(0) used frequently in
5920                  * Array methods.
5921                  */
5922                 else if (((strcmp (cmethod->name, "GetLength") == 0 && fsig->param_count + fsig->hasthis == 2) ||
5923                          (strcmp (cmethod->name, "GetLowerBound") == 0 && fsig->param_count + fsig->hasthis == 2)) &&
5924                          args [1]->opcode == OP_ICONST && args [1]->inst_c0 == 0) {
5925                         int dreg = alloc_ireg (cfg);
5926                         int bounds_reg = alloc_ireg_mp (cfg);
5927                         MonoBasicBlock *end_bb, *szarray_bb;
5928                         gboolean get_length = strcmp (cmethod->name, "GetLength") == 0;
5929
5930                         NEW_BBLOCK (cfg, end_bb);
5931                         NEW_BBLOCK (cfg, szarray_bb);
5932
5933                         EMIT_NEW_LOAD_MEMBASE_FAULT (cfg, ins, OP_LOAD_MEMBASE, bounds_reg,
5934                                                                                  args [0]->dreg, MONO_STRUCT_OFFSET (MonoArray, bounds));
5935                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, bounds_reg, 0);
5936                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, szarray_bb);
5937                         /* Non-szarray case */
5938                         if (get_length)
5939                                 EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOADI4_MEMBASE, dreg,
5940                                                                            bounds_reg, MONO_STRUCT_OFFSET (MonoArrayBounds, length));
5941                         else
5942                                 EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOADI4_MEMBASE, dreg,
5943                                                                            bounds_reg, MONO_STRUCT_OFFSET (MonoArrayBounds, lower_bound));
5944                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
5945                         MONO_START_BB (cfg, szarray_bb);
5946                         /* Szarray case */
5947                         if (get_length)
5948                                 EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOADI4_MEMBASE, dreg,
5949                                                                            args [0]->dreg, MONO_STRUCT_OFFSET (MonoArray, max_length));
5950                         else
5951                                 MONO_EMIT_NEW_ICONST (cfg, dreg, 0);
5952                         MONO_START_BB (cfg, end_bb);
5953
5954                         EMIT_NEW_UNALU (cfg, ins, OP_MOVE, dreg, dreg);
5955                         ins->type = STACK_I4;
5956                         
5957                         return ins;
5958                 }
5959 #endif
5960
5961                 if (cmethod->name [0] != 'g')
5962                         return NULL;
5963
5964                 if (strcmp (cmethod->name, "get_Rank") == 0 && fsig->param_count + fsig->hasthis == 1) {
5965                         int dreg = alloc_ireg (cfg);
5966                         int vtable_reg = alloc_preg (cfg);
5967                         MONO_EMIT_NEW_LOAD_MEMBASE_OP_FAULT (cfg, OP_LOAD_MEMBASE, vtable_reg, 
5968                                                                                                  args [0]->dreg, MONO_STRUCT_OFFSET (MonoObject, vtable));
5969                         EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOADU1_MEMBASE, dreg,
5970                                                                    vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, rank));
5971                         type_from_op (cfg, ins, NULL, NULL);
5972
5973                         return ins;
5974                 } else if (strcmp (cmethod->name, "get_Length") == 0 && fsig->param_count + fsig->hasthis == 1) {
5975                         int dreg = alloc_ireg (cfg);
5976
5977                         EMIT_NEW_LOAD_MEMBASE_FAULT (cfg, ins, OP_LOADI4_MEMBASE, dreg, 
5978                                                                                  args [0]->dreg, MONO_STRUCT_OFFSET (MonoArray, max_length));
5979                         type_from_op (cfg, ins, NULL, NULL);
5980
5981                         return ins;
5982                 } else
5983                         return NULL;
5984         } else if (cmethod->klass == runtime_helpers_class) {
5985
5986                 if (strcmp (cmethod->name, "get_OffsetToStringData") == 0 && fsig->param_count == 0) {
5987                         EMIT_NEW_ICONST (cfg, ins, MONO_STRUCT_OFFSET (MonoString, chars));
5988                         return ins;
5989                 } else
5990                         return NULL;
5991         } else if (cmethod->klass == mono_defaults.thread_class) {
5992                 if (strcmp (cmethod->name, "SpinWait_nop") == 0 && fsig->param_count == 0) {
5993                         MONO_INST_NEW (cfg, ins, OP_RELAXED_NOP);
5994                         MONO_ADD_INS (cfg->cbb, ins);
5995                         return ins;
5996                 } else if (strcmp (cmethod->name, "MemoryBarrier") == 0 && fsig->param_count == 0) {
5997                         return emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_SEQ);
5998                 } else if (!strcmp (cmethod->name, "VolatileRead") && fsig->param_count == 1) {
5999                         guint32 opcode = 0;
6000                         gboolean is_ref = mini_type_is_reference (fsig->params [0]);
6001
6002                         if (fsig->params [0]->type == MONO_TYPE_I1)
6003                                 opcode = OP_LOADI1_MEMBASE;
6004                         else if (fsig->params [0]->type == MONO_TYPE_U1)
6005                                 opcode = OP_LOADU1_MEMBASE;
6006                         else if (fsig->params [0]->type == MONO_TYPE_I2)
6007                                 opcode = OP_LOADI2_MEMBASE;
6008                         else if (fsig->params [0]->type == MONO_TYPE_U2)
6009                                 opcode = OP_LOADU2_MEMBASE;
6010                         else if (fsig->params [0]->type == MONO_TYPE_I4)
6011                                 opcode = OP_LOADI4_MEMBASE;
6012                         else if (fsig->params [0]->type == MONO_TYPE_U4)
6013                                 opcode = OP_LOADU4_MEMBASE;
6014                         else if (fsig->params [0]->type == MONO_TYPE_I8 || fsig->params [0]->type == MONO_TYPE_U8)
6015                                 opcode = OP_LOADI8_MEMBASE;
6016                         else if (fsig->params [0]->type == MONO_TYPE_R4)
6017                                 opcode = OP_LOADR4_MEMBASE;
6018                         else if (fsig->params [0]->type == MONO_TYPE_R8)
6019                                 opcode = OP_LOADR8_MEMBASE;
6020                         else if (is_ref || fsig->params [0]->type == MONO_TYPE_I || fsig->params [0]->type == MONO_TYPE_U)
6021                                 opcode = OP_LOAD_MEMBASE;
6022
6023                         if (opcode) {
6024                                 MONO_INST_NEW (cfg, ins, opcode);
6025                                 ins->inst_basereg = args [0]->dreg;
6026                                 ins->inst_offset = 0;
6027                                 MONO_ADD_INS (cfg->cbb, ins);
6028
6029                                 switch (fsig->params [0]->type) {
6030                                 case MONO_TYPE_I1:
6031                                 case MONO_TYPE_U1:
6032                                 case MONO_TYPE_I2:
6033                                 case MONO_TYPE_U2:
6034                                 case MONO_TYPE_I4:
6035                                 case MONO_TYPE_U4:
6036                                         ins->dreg = mono_alloc_ireg (cfg);
6037                                         ins->type = STACK_I4;
6038                                         break;
6039                                 case MONO_TYPE_I8:
6040                                 case MONO_TYPE_U8:
6041                                         ins->dreg = mono_alloc_lreg (cfg);
6042                                         ins->type = STACK_I8;
6043                                         break;
6044                                 case MONO_TYPE_I:
6045                                 case MONO_TYPE_U:
6046                                         ins->dreg = mono_alloc_ireg (cfg);
6047 #if SIZEOF_REGISTER == 8
6048                                         ins->type = STACK_I8;
6049 #else
6050                                         ins->type = STACK_I4;
6051 #endif
6052                                         break;
6053                                 case MONO_TYPE_R4:
6054                                 case MONO_TYPE_R8:
6055                                         ins->dreg = mono_alloc_freg (cfg);
6056                                         ins->type = STACK_R8;
6057                                         break;
6058                                 default:
6059                                         g_assert (mini_type_is_reference (fsig->params [0]));
6060                                         ins->dreg = mono_alloc_ireg_ref (cfg);
6061                                         ins->type = STACK_OBJ;
6062                                         break;
6063                                 }
6064
6065                                 if (opcode == OP_LOADI8_MEMBASE)
6066                                         ins = mono_decompose_opcode (cfg, ins);
6067
6068                                 emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_ACQ);
6069
6070                                 return ins;
6071                         }
6072                 } else if (!strcmp (cmethod->name, "VolatileWrite") && fsig->param_count == 2) {
6073                         guint32 opcode = 0;
6074                         gboolean is_ref = mini_type_is_reference (fsig->params [0]);
6075
6076                         if (fsig->params [0]->type == MONO_TYPE_I1 || fsig->params [0]->type == MONO_TYPE_U1)
6077                                 opcode = OP_STOREI1_MEMBASE_REG;
6078                         else if (fsig->params [0]->type == MONO_TYPE_I2 || fsig->params [0]->type == MONO_TYPE_U2)
6079                                 opcode = OP_STOREI2_MEMBASE_REG;
6080                         else if (fsig->params [0]->type == MONO_TYPE_I4 || fsig->params [0]->type == MONO_TYPE_U4)
6081                                 opcode = OP_STOREI4_MEMBASE_REG;
6082                         else if (fsig->params [0]->type == MONO_TYPE_I8 || fsig->params [0]->type == MONO_TYPE_U8)
6083                                 opcode = OP_STOREI8_MEMBASE_REG;
6084                         else if (fsig->params [0]->type == MONO_TYPE_R4)
6085                                 opcode = OP_STORER4_MEMBASE_REG;
6086                         else if (fsig->params [0]->type == MONO_TYPE_R8)
6087                                 opcode = OP_STORER8_MEMBASE_REG;
6088                         else if (is_ref || fsig->params [0]->type == MONO_TYPE_I || fsig->params [0]->type == MONO_TYPE_U)
6089                                 opcode = OP_STORE_MEMBASE_REG;
6090
6091                         if (opcode) {
6092                                 emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL);
6093
6094                                 MONO_INST_NEW (cfg, ins, opcode);
6095                                 ins->sreg1 = args [1]->dreg;
6096                                 ins->inst_destbasereg = args [0]->dreg;
6097                                 ins->inst_offset = 0;
6098                                 MONO_ADD_INS (cfg->cbb, ins);
6099
6100                                 if (opcode == OP_STOREI8_MEMBASE_REG)
6101                                         ins = mono_decompose_opcode (cfg, ins);
6102
6103                                 return ins;
6104                         }
6105                 }
6106         } else if (cmethod->klass->image == mono_defaults.corlib &&
6107                            (strcmp (cmethod->klass->name_space, "System.Threading") == 0) &&
6108                            (strcmp (cmethod->klass->name, "Interlocked") == 0)) {
6109                 ins = NULL;
6110
6111 #if SIZEOF_REGISTER == 8
6112                 if (!cfg->llvm_only && strcmp (cmethod->name, "Read") == 0 && fsig->param_count == 1 && (fsig->params [0]->type == MONO_TYPE_I8)) {
6113                         if (!cfg->llvm_only && mono_arch_opcode_supported (OP_ATOMIC_LOAD_I8)) {
6114                                 MONO_INST_NEW (cfg, ins, OP_ATOMIC_LOAD_I8);
6115                                 ins->dreg = mono_alloc_preg (cfg);
6116                                 ins->sreg1 = args [0]->dreg;
6117                                 ins->type = STACK_I8;
6118                                 ins->backend.memory_barrier_kind = MONO_MEMORY_BARRIER_SEQ;
6119                                 MONO_ADD_INS (cfg->cbb, ins);
6120                         } else {
6121                                 MonoInst *load_ins;
6122
6123                                 emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_SEQ);
6124
6125                                 /* 64 bit reads are already atomic */
6126                                 MONO_INST_NEW (cfg, load_ins, OP_LOADI8_MEMBASE);
6127                                 load_ins->dreg = mono_alloc_preg (cfg);
6128                                 load_ins->inst_basereg = args [0]->dreg;
6129                                 load_ins->inst_offset = 0;
6130                                 load_ins->type = STACK_I8;
6131                                 MONO_ADD_INS (cfg->cbb, load_ins);
6132
6133                                 emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_SEQ);
6134
6135                                 ins = load_ins;
6136                         }
6137                 }
6138 #endif
6139
6140                 if (strcmp (cmethod->name, "Increment") == 0 && fsig->param_count == 1) {
6141                         MonoInst *ins_iconst;
6142                         guint32 opcode = 0;
6143
6144                         if (fsig->params [0]->type == MONO_TYPE_I4) {
6145                                 opcode = OP_ATOMIC_ADD_I4;
6146                                 cfg->has_atomic_add_i4 = TRUE;
6147                         }
6148 #if SIZEOF_REGISTER == 8
6149                         else if (fsig->params [0]->type == MONO_TYPE_I8)
6150                                 opcode = OP_ATOMIC_ADD_I8;
6151 #endif
6152                         if (opcode) {
6153                                 if (!mono_arch_opcode_supported (opcode))
6154                                         return NULL;
6155                                 MONO_INST_NEW (cfg, ins_iconst, OP_ICONST);
6156                                 ins_iconst->inst_c0 = 1;
6157                                 ins_iconst->dreg = mono_alloc_ireg (cfg);
6158                                 MONO_ADD_INS (cfg->cbb, ins_iconst);
6159
6160                                 MONO_INST_NEW (cfg, ins, opcode);
6161                                 ins->dreg = mono_alloc_ireg (cfg);
6162                                 ins->inst_basereg = args [0]->dreg;
6163                                 ins->inst_offset = 0;
6164                                 ins->sreg2 = ins_iconst->dreg;
6165                                 ins->type = (opcode == OP_ATOMIC_ADD_I4) ? STACK_I4 : STACK_I8;
6166                                 MONO_ADD_INS (cfg->cbb, ins);
6167                         }
6168                 } else if (strcmp (cmethod->name, "Decrement") == 0 && fsig->param_count == 1) {
6169                         MonoInst *ins_iconst;
6170                         guint32 opcode = 0;
6171
6172                         if (fsig->params [0]->type == MONO_TYPE_I4) {
6173                                 opcode = OP_ATOMIC_ADD_I4;
6174                                 cfg->has_atomic_add_i4 = TRUE;
6175                         }
6176 #if SIZEOF_REGISTER == 8
6177                         else if (fsig->params [0]->type == MONO_TYPE_I8)
6178                                 opcode = OP_ATOMIC_ADD_I8;
6179 #endif
6180                         if (opcode) {
6181                                 if (!mono_arch_opcode_supported (opcode))
6182                                         return NULL;
6183                                 MONO_INST_NEW (cfg, ins_iconst, OP_ICONST);
6184                                 ins_iconst->inst_c0 = -1;
6185                                 ins_iconst->dreg = mono_alloc_ireg (cfg);
6186                                 MONO_ADD_INS (cfg->cbb, ins_iconst);
6187
6188                                 MONO_INST_NEW (cfg, ins, opcode);
6189                                 ins->dreg = mono_alloc_ireg (cfg);
6190                                 ins->inst_basereg = args [0]->dreg;
6191                                 ins->inst_offset = 0;
6192                                 ins->sreg2 = ins_iconst->dreg;
6193                                 ins->type = (opcode == OP_ATOMIC_ADD_I4) ? STACK_I4 : STACK_I8;
6194                                 MONO_ADD_INS (cfg->cbb, ins);
6195                         }
6196                 } else if (strcmp (cmethod->name, "Add") == 0 && fsig->param_count == 2) {
6197                         guint32 opcode = 0;
6198
6199                         if (fsig->params [0]->type == MONO_TYPE_I4) {
6200                                 opcode = OP_ATOMIC_ADD_I4;
6201                                 cfg->has_atomic_add_i4 = TRUE;
6202                         }
6203 #if SIZEOF_REGISTER == 8
6204                         else if (fsig->params [0]->type == MONO_TYPE_I8)
6205                                 opcode = OP_ATOMIC_ADD_I8;
6206 #endif
6207                         if (opcode) {
6208                                 if (!mono_arch_opcode_supported (opcode))
6209                                         return NULL;
6210                                 MONO_INST_NEW (cfg, ins, opcode);
6211                                 ins->dreg = mono_alloc_ireg (cfg);
6212                                 ins->inst_basereg = args [0]->dreg;
6213                                 ins->inst_offset = 0;
6214                                 ins->sreg2 = args [1]->dreg;
6215                                 ins->type = (opcode == OP_ATOMIC_ADD_I4) ? STACK_I4 : STACK_I8;
6216                                 MONO_ADD_INS (cfg->cbb, ins);
6217                         }
6218                 }
6219                 else if (strcmp (cmethod->name, "Exchange") == 0 && fsig->param_count == 2) {
6220                         MonoInst *f2i = NULL, *i2f;
6221                         guint32 opcode, f2i_opcode, i2f_opcode;
6222                         gboolean is_ref = mini_type_is_reference (fsig->params [0]);
6223                         gboolean is_float = fsig->params [0]->type == MONO_TYPE_R4 || fsig->params [0]->type == MONO_TYPE_R8;
6224
6225                         if (fsig->params [0]->type == MONO_TYPE_I4 ||
6226                             fsig->params [0]->type == MONO_TYPE_R4) {
6227                                 opcode = OP_ATOMIC_EXCHANGE_I4;
6228                                 f2i_opcode = OP_MOVE_F_TO_I4;
6229                                 i2f_opcode = OP_MOVE_I4_TO_F;
6230                                 cfg->has_atomic_exchange_i4 = TRUE;
6231                         }
6232 #if SIZEOF_REGISTER == 8
6233                         else if (is_ref ||
6234                                  fsig->params [0]->type == MONO_TYPE_I8 ||
6235                                  fsig->params [0]->type == MONO_TYPE_R8 ||
6236                                  fsig->params [0]->type == MONO_TYPE_I) {
6237                                 opcode = OP_ATOMIC_EXCHANGE_I8;
6238                                 f2i_opcode = OP_MOVE_F_TO_I8;
6239                                 i2f_opcode = OP_MOVE_I8_TO_F;
6240                         }
6241 #else
6242                         else if (is_ref || fsig->params [0]->type == MONO_TYPE_I) {
6243                                 opcode = OP_ATOMIC_EXCHANGE_I4;
6244                                 cfg->has_atomic_exchange_i4 = TRUE;
6245                         }
6246 #endif
6247                         else
6248                                 return NULL;
6249
6250                         if (!mono_arch_opcode_supported (opcode))
6251                                 return NULL;
6252
6253                         if (is_float) {
6254                                 /* TODO: Decompose these opcodes instead of bailing here. */
6255                                 if (COMPILE_SOFT_FLOAT (cfg))
6256                                         return NULL;
6257
6258                                 MONO_INST_NEW (cfg, f2i, f2i_opcode);
6259                                 f2i->dreg = mono_alloc_ireg (cfg);
6260                                 f2i->sreg1 = args [1]->dreg;
6261                                 if (f2i_opcode == OP_MOVE_F_TO_I4)
6262                                         f2i->backend.spill_var = mini_get_int_to_float_spill_area (cfg);
6263                                 MONO_ADD_INS (cfg->cbb, f2i);
6264                         }
6265
6266                         MONO_INST_NEW (cfg, ins, opcode);
6267                         ins->dreg = is_ref ? mono_alloc_ireg_ref (cfg) : mono_alloc_ireg (cfg);
6268                         ins->inst_basereg = args [0]->dreg;
6269                         ins->inst_offset = 0;
6270                         ins->sreg2 = is_float ? f2i->dreg : args [1]->dreg;
6271                         MONO_ADD_INS (cfg->cbb, ins);
6272
6273                         switch (fsig->params [0]->type) {
6274                         case MONO_TYPE_I4:
6275                                 ins->type = STACK_I4;
6276                                 break;
6277                         case MONO_TYPE_I8:
6278                                 ins->type = STACK_I8;
6279                                 break;
6280                         case MONO_TYPE_I:
6281 #if SIZEOF_REGISTER == 8
6282                                 ins->type = STACK_I8;
6283 #else
6284                                 ins->type = STACK_I4;
6285 #endif
6286                                 break;
6287                         case MONO_TYPE_R4:
6288                         case MONO_TYPE_R8:
6289                                 ins->type = STACK_R8;
6290                                 break;
6291                         default:
6292                                 g_assert (mini_type_is_reference (fsig->params [0]));
6293                                 ins->type = STACK_OBJ;
6294                                 break;
6295                         }
6296
6297                         if (is_float) {
6298                                 MONO_INST_NEW (cfg, i2f, i2f_opcode);
6299                                 i2f->dreg = mono_alloc_freg (cfg);
6300                                 i2f->sreg1 = ins->dreg;
6301                                 i2f->type = STACK_R8;
6302                                 if (i2f_opcode == OP_MOVE_I4_TO_F)
6303                                         i2f->backend.spill_var = mini_get_int_to_float_spill_area (cfg);
6304                                 MONO_ADD_INS (cfg->cbb, i2f);
6305
6306                                 ins = i2f;
6307                         }
6308
6309                         if (cfg->gen_write_barriers && is_ref)
6310                                 emit_write_barrier (cfg, args [0], args [1]);
6311                 }
6312                 else if ((strcmp (cmethod->name, "CompareExchange") == 0) && fsig->param_count == 3) {
6313                         MonoInst *f2i_new = NULL, *f2i_cmp = NULL, *i2f;
6314                         guint32 opcode, f2i_opcode, i2f_opcode;
6315                         gboolean is_ref = mini_type_is_reference (fsig->params [1]);
6316                         gboolean is_float = fsig->params [1]->type == MONO_TYPE_R4 || fsig->params [1]->type == MONO_TYPE_R8;
6317
6318                         if (fsig->params [1]->type == MONO_TYPE_I4 ||
6319                             fsig->params [1]->type == MONO_TYPE_R4) {
6320                                 opcode = OP_ATOMIC_CAS_I4;
6321                                 f2i_opcode = OP_MOVE_F_TO_I4;
6322                                 i2f_opcode = OP_MOVE_I4_TO_F;
6323                                 cfg->has_atomic_cas_i4 = TRUE;
6324                         }
6325 #if SIZEOF_REGISTER == 8
6326                         else if (is_ref ||
6327                                  fsig->params [1]->type == MONO_TYPE_I8 ||
6328                                  fsig->params [1]->type == MONO_TYPE_R8 ||
6329                                  fsig->params [1]->type == MONO_TYPE_I) {
6330                                 opcode = OP_ATOMIC_CAS_I8;
6331                                 f2i_opcode = OP_MOVE_F_TO_I8;
6332                                 i2f_opcode = OP_MOVE_I8_TO_F;
6333                         }
6334 #else
6335                         else if (is_ref || fsig->params [1]->type == MONO_TYPE_I) {
6336                                 opcode = OP_ATOMIC_CAS_I4;
6337                                 cfg->has_atomic_cas_i4 = TRUE;
6338                         }
6339 #endif
6340                         else
6341                                 return NULL;
6342
6343                         if (!mono_arch_opcode_supported (opcode))
6344                                 return NULL;
6345
6346                         if (is_float) {
6347                                 /* TODO: Decompose these opcodes instead of bailing here. */
6348                                 if (COMPILE_SOFT_FLOAT (cfg))
6349                                         return NULL;
6350
6351                                 MONO_INST_NEW (cfg, f2i_new, f2i_opcode);
6352                                 f2i_new->dreg = mono_alloc_ireg (cfg);
6353                                 f2i_new->sreg1 = args [1]->dreg;
6354                                 if (f2i_opcode == OP_MOVE_F_TO_I4)
6355                                         f2i_new->backend.spill_var = mini_get_int_to_float_spill_area (cfg);
6356                                 MONO_ADD_INS (cfg->cbb, f2i_new);
6357
6358                                 MONO_INST_NEW (cfg, f2i_cmp, f2i_opcode);
6359                                 f2i_cmp->dreg = mono_alloc_ireg (cfg);
6360                                 f2i_cmp->sreg1 = args [2]->dreg;
6361                                 if (f2i_opcode == OP_MOVE_F_TO_I4)
6362                                         f2i_cmp->backend.spill_var = mini_get_int_to_float_spill_area (cfg);
6363                                 MONO_ADD_INS (cfg->cbb, f2i_cmp);
6364                         }
6365
6366                         MONO_INST_NEW (cfg, ins, opcode);
6367                         ins->dreg = is_ref ? alloc_ireg_ref (cfg) : alloc_ireg (cfg);
6368                         ins->sreg1 = args [0]->dreg;
6369                         ins->sreg2 = is_float ? f2i_new->dreg : args [1]->dreg;
6370                         ins->sreg3 = is_float ? f2i_cmp->dreg : args [2]->dreg;
6371                         MONO_ADD_INS (cfg->cbb, ins);
6372
6373                         switch (fsig->params [1]->type) {
6374                         case MONO_TYPE_I4:
6375                                 ins->type = STACK_I4;
6376                                 break;
6377                         case MONO_TYPE_I8:
6378                                 ins->type = STACK_I8;
6379                                 break;
6380                         case MONO_TYPE_I:
6381 #if SIZEOF_REGISTER == 8
6382                                 ins->type = STACK_I8;
6383 #else
6384                                 ins->type = STACK_I4;
6385 #endif
6386                                 break;
6387                         case MONO_TYPE_R4:
6388                                 ins->type = cfg->r4_stack_type;
6389                                 break;
6390                         case MONO_TYPE_R8:
6391                                 ins->type = STACK_R8;
6392                                 break;
6393                         default:
6394                                 g_assert (mini_type_is_reference (fsig->params [1]));
6395                                 ins->type = STACK_OBJ;
6396                                 break;
6397                         }
6398
6399                         if (is_float) {
6400                                 MONO_INST_NEW (cfg, i2f, i2f_opcode);
6401                                 i2f->dreg = mono_alloc_freg (cfg);
6402                                 i2f->sreg1 = ins->dreg;
6403                                 i2f->type = STACK_R8;
6404                                 if (i2f_opcode == OP_MOVE_I4_TO_F)
6405                                         i2f->backend.spill_var = mini_get_int_to_float_spill_area (cfg);
6406                                 MONO_ADD_INS (cfg->cbb, i2f);
6407
6408                                 ins = i2f;
6409                         }
6410
6411                         if (cfg->gen_write_barriers && is_ref)
6412                                 emit_write_barrier (cfg, args [0], args [1]);
6413                 }
6414                 else if ((strcmp (cmethod->name, "CompareExchange") == 0) && fsig->param_count == 4 &&
6415                          fsig->params [1]->type == MONO_TYPE_I4) {
6416                         MonoInst *cmp, *ceq;
6417
6418                         if (!mono_arch_opcode_supported (OP_ATOMIC_CAS_I4))
6419                                 return NULL;
6420
6421                         /* int32 r = CAS (location, value, comparand); */
6422                         MONO_INST_NEW (cfg, ins, OP_ATOMIC_CAS_I4);
6423                         ins->dreg = alloc_ireg (cfg);
6424                         ins->sreg1 = args [0]->dreg;
6425                         ins->sreg2 = args [1]->dreg;
6426                         ins->sreg3 = args [2]->dreg;
6427                         ins->type = STACK_I4;
6428                         MONO_ADD_INS (cfg->cbb, ins);
6429
6430                         /* bool result = r == comparand; */
6431                         MONO_INST_NEW (cfg, cmp, OP_ICOMPARE);
6432                         cmp->sreg1 = ins->dreg;
6433                         cmp->sreg2 = args [2]->dreg;
6434                         cmp->type = STACK_I4;
6435                         MONO_ADD_INS (cfg->cbb, cmp);
6436
6437                         MONO_INST_NEW (cfg, ceq, OP_ICEQ);
6438                         ceq->dreg = alloc_ireg (cfg);
6439                         ceq->type = STACK_I4;
6440                         MONO_ADD_INS (cfg->cbb, ceq);
6441
6442                         /* *success = result; */
6443                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, args [3]->dreg, 0, ceq->dreg);
6444
6445                         cfg->has_atomic_cas_i4 = TRUE;
6446                 }
6447                 else if (strcmp (cmethod->name, "MemoryBarrier") == 0 && fsig->param_count == 0)
6448                         ins = emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_SEQ);
6449
6450                 if (ins)
6451                         return ins;
6452         } else if (cmethod->klass->image == mono_defaults.corlib &&
6453                            (strcmp (cmethod->klass->name_space, "System.Threading") == 0) &&
6454                            (strcmp (cmethod->klass->name, "Volatile") == 0)) {
6455                 ins = NULL;
6456
6457                 if (!cfg->llvm_only && !strcmp (cmethod->name, "Read") && fsig->param_count == 1) {
6458                         guint32 opcode = 0;
6459                         gboolean is_ref = mini_type_is_reference (fsig->params [0]);
6460                         gboolean is_float = fsig->params [0]->type == MONO_TYPE_R4 || fsig->params [0]->type == MONO_TYPE_R8;
6461
6462                         if (fsig->params [0]->type == MONO_TYPE_I1)
6463                                 opcode = OP_ATOMIC_LOAD_I1;
6464                         else if (fsig->params [0]->type == MONO_TYPE_U1 || fsig->params [0]->type == MONO_TYPE_BOOLEAN)
6465                                 opcode = OP_ATOMIC_LOAD_U1;
6466                         else if (fsig->params [0]->type == MONO_TYPE_I2)
6467                                 opcode = OP_ATOMIC_LOAD_I2;
6468                         else if (fsig->params [0]->type == MONO_TYPE_U2)
6469                                 opcode = OP_ATOMIC_LOAD_U2;
6470                         else if (fsig->params [0]->type == MONO_TYPE_I4)
6471                                 opcode = OP_ATOMIC_LOAD_I4;
6472                         else if (fsig->params [0]->type == MONO_TYPE_U4)
6473                                 opcode = OP_ATOMIC_LOAD_U4;
6474                         else if (fsig->params [0]->type == MONO_TYPE_R4)
6475                                 opcode = OP_ATOMIC_LOAD_R4;
6476                         else if (fsig->params [0]->type == MONO_TYPE_R8)
6477                                 opcode = OP_ATOMIC_LOAD_R8;
6478 #if SIZEOF_REGISTER == 8
6479                         else if (fsig->params [0]->type == MONO_TYPE_I8 || fsig->params [0]->type == MONO_TYPE_I)
6480                                 opcode = OP_ATOMIC_LOAD_I8;
6481                         else if (is_ref || fsig->params [0]->type == MONO_TYPE_U8 || fsig->params [0]->type == MONO_TYPE_U)
6482                                 opcode = OP_ATOMIC_LOAD_U8;
6483 #else
6484                         else if (fsig->params [0]->type == MONO_TYPE_I)
6485                                 opcode = OP_ATOMIC_LOAD_I4;
6486                         else if (is_ref || fsig->params [0]->type == MONO_TYPE_U)
6487                                 opcode = OP_ATOMIC_LOAD_U4;
6488 #endif
6489
6490                         if (opcode) {
6491                                 if (!mono_arch_opcode_supported (opcode))
6492                                         return NULL;
6493
6494                                 MONO_INST_NEW (cfg, ins, opcode);
6495                                 ins->dreg = is_ref ? mono_alloc_ireg_ref (cfg) : (is_float ? mono_alloc_freg (cfg) : mono_alloc_ireg (cfg));
6496                                 ins->sreg1 = args [0]->dreg;
6497                                 ins->backend.memory_barrier_kind = MONO_MEMORY_BARRIER_ACQ;
6498                                 MONO_ADD_INS (cfg->cbb, ins);
6499
6500                                 switch (fsig->params [0]->type) {
6501                                 case MONO_TYPE_BOOLEAN:
6502                                 case MONO_TYPE_I1:
6503                                 case MONO_TYPE_U1:
6504                                 case MONO_TYPE_I2:
6505                                 case MONO_TYPE_U2:
6506                                 case MONO_TYPE_I4:
6507                                 case MONO_TYPE_U4:
6508                                         ins->type = STACK_I4;
6509                                         break;
6510                                 case MONO_TYPE_I8:
6511                                 case MONO_TYPE_U8:
6512                                         ins->type = STACK_I8;
6513                                         break;
6514                                 case MONO_TYPE_I:
6515                                 case MONO_TYPE_U:
6516 #if SIZEOF_REGISTER == 8
6517                                         ins->type = STACK_I8;
6518 #else
6519                                         ins->type = STACK_I4;
6520 #endif
6521                                         break;
6522                                 case MONO_TYPE_R4:
6523                                         ins->type = cfg->r4_stack_type;
6524                                         break;
6525                                 case MONO_TYPE_R8:
6526                                         ins->type = STACK_R8;
6527                                         break;
6528                                 default:
6529                                         g_assert (mini_type_is_reference (fsig->params [0]));
6530                                         ins->type = STACK_OBJ;
6531                                         break;
6532                                 }
6533                         }
6534                 }
6535
6536                 if (!cfg->llvm_only && !strcmp (cmethod->name, "Write") && fsig->param_count == 2) {
6537                         guint32 opcode = 0;
6538                         gboolean is_ref = mini_type_is_reference (fsig->params [0]);
6539
6540                         if (fsig->params [0]->type == MONO_TYPE_I1)
6541                                 opcode = OP_ATOMIC_STORE_I1;
6542                         else if (fsig->params [0]->type == MONO_TYPE_U1 || fsig->params [0]->type == MONO_TYPE_BOOLEAN)
6543                                 opcode = OP_ATOMIC_STORE_U1;
6544                         else if (fsig->params [0]->type == MONO_TYPE_I2)
6545                                 opcode = OP_ATOMIC_STORE_I2;
6546                         else if (fsig->params [0]->type == MONO_TYPE_U2)
6547                                 opcode = OP_ATOMIC_STORE_U2;
6548                         else if (fsig->params [0]->type == MONO_TYPE_I4)
6549                                 opcode = OP_ATOMIC_STORE_I4;
6550                         else if (fsig->params [0]->type == MONO_TYPE_U4)
6551                                 opcode = OP_ATOMIC_STORE_U4;
6552                         else if (fsig->params [0]->type == MONO_TYPE_R4)
6553                                 opcode = OP_ATOMIC_STORE_R4;
6554                         else if (fsig->params [0]->type == MONO_TYPE_R8)
6555                                 opcode = OP_ATOMIC_STORE_R8;
6556 #if SIZEOF_REGISTER == 8
6557                         else if (fsig->params [0]->type == MONO_TYPE_I8 || fsig->params [0]->type == MONO_TYPE_I)
6558                                 opcode = OP_ATOMIC_STORE_I8;
6559                         else if (is_ref || fsig->params [0]->type == MONO_TYPE_U8 || fsig->params [0]->type == MONO_TYPE_U)
6560                                 opcode = OP_ATOMIC_STORE_U8;
6561 #else
6562                         else if (fsig->params [0]->type == MONO_TYPE_I)
6563                                 opcode = OP_ATOMIC_STORE_I4;
6564                         else if (is_ref || fsig->params [0]->type == MONO_TYPE_U)
6565                                 opcode = OP_ATOMIC_STORE_U4;
6566 #endif
6567
6568                         if (opcode) {
6569                                 if (!mono_arch_opcode_supported (opcode))
6570                                         return NULL;
6571
6572                                 MONO_INST_NEW (cfg, ins, opcode);
6573                                 ins->dreg = args [0]->dreg;
6574                                 ins->sreg1 = args [1]->dreg;
6575                                 ins->backend.memory_barrier_kind = MONO_MEMORY_BARRIER_REL;
6576                                 MONO_ADD_INS (cfg->cbb, ins);
6577
6578                                 if (cfg->gen_write_barriers && is_ref)
6579                                         emit_write_barrier (cfg, args [0], args [1]);
6580                         }
6581                 }
6582
6583                 if (ins)
6584                         return ins;
6585         } else if (cmethod->klass->image == mono_defaults.corlib &&
6586                            (strcmp (cmethod->klass->name_space, "System.Diagnostics") == 0) &&
6587                            (strcmp (cmethod->klass->name, "Debugger") == 0)) {
6588                 if (!strcmp (cmethod->name, "Break") && fsig->param_count == 0) {
6589                         if (should_insert_brekpoint (cfg->method)) {
6590                                 ins = mono_emit_jit_icall (cfg, mono_debugger_agent_user_break, NULL);
6591                         } else {
6592                                 MONO_INST_NEW (cfg, ins, OP_NOP);
6593                                 MONO_ADD_INS (cfg->cbb, ins);
6594                         }
6595                         return ins;
6596                 }
6597         } else if (cmethod->klass->image == mono_defaults.corlib &&
6598                    (strcmp (cmethod->klass->name_space, "System") == 0) &&
6599                    (strcmp (cmethod->klass->name, "Environment") == 0)) {
6600                 if (!strcmp (cmethod->name, "get_IsRunningOnWindows") && fsig->param_count == 0) {
6601 #ifdef TARGET_WIN32
6602                         EMIT_NEW_ICONST (cfg, ins, 1);
6603 #else
6604                         EMIT_NEW_ICONST (cfg, ins, 0);
6605 #endif
6606                 }
6607         } else if (cmethod->klass->image == mono_defaults.corlib &&
6608                            (strcmp (cmethod->klass->name_space, "System.Reflection") == 0) &&
6609                            (strcmp (cmethod->klass->name, "Assembly") == 0)) {
6610                 if (cfg->llvm_only && !strcmp (cmethod->name, "GetExecutingAssembly")) {
6611                         /* No stack walks are current available, so implement this as an intrinsic */
6612                         MonoInst *assembly_ins;
6613
6614                         EMIT_NEW_AOTCONST (cfg, assembly_ins, MONO_PATCH_INFO_IMAGE, cfg->method->klass->image);
6615                         ins = mono_emit_jit_icall (cfg, mono_get_assembly_object, &assembly_ins);
6616                         return ins;
6617                 }
6618         } else if (cmethod->klass == mono_defaults.math_class) {
6619                 /* 
6620                  * There is general branchless code for Min/Max, but it does not work for 
6621                  * all inputs:
6622                  * http://everything2.com/?node_id=1051618
6623                  */
6624         } else if (((!strcmp (cmethod->klass->image->assembly->aname.name, "MonoMac") ||
6625                     !strcmp (cmethod->klass->image->assembly->aname.name, "monotouch")) &&
6626                                 !strcmp (cmethod->klass->name_space, "XamCore.ObjCRuntime") &&
6627                                 !strcmp (cmethod->klass->name, "Selector")) ||
6628                            (!strcmp (cmethod->klass->image->assembly->aname.name, "Xamarin.iOS") &&
6629                                 !strcmp (cmethod->klass->name_space, "ObjCRuntime") &&
6630                                 !strcmp (cmethod->klass->name, "Selector"))
6631                            ) {
6632                 if (cfg->backend->have_objc_get_selector &&
6633                         !strcmp (cmethod->name, "GetHandle") && fsig->param_count == 1 &&
6634                     (args [0]->opcode == OP_GOT_ENTRY || args [0]->opcode == OP_AOTCONST) &&
6635                     cfg->compile_aot) {
6636                         MonoInst *pi;
6637                         MonoJumpInfoToken *ji;
6638                         MonoString *s;
6639
6640                         cfg->disable_llvm = TRUE;
6641
6642                         if (args [0]->opcode == OP_GOT_ENTRY) {
6643                                 pi = args [0]->inst_p1;
6644                                 g_assert (pi->opcode == OP_PATCH_INFO);
6645                                 g_assert (GPOINTER_TO_INT (pi->inst_p1) == MONO_PATCH_INFO_LDSTR);
6646                                 ji = pi->inst_p0;
6647                         } else {
6648                                 g_assert (GPOINTER_TO_INT (args [0]->inst_p1) == MONO_PATCH_INFO_LDSTR);
6649                                 ji = args [0]->inst_p0;
6650                         }
6651
6652                         NULLIFY_INS (args [0]);
6653
6654                         // FIXME: Ugly
6655                         s = mono_ldstr (cfg->domain, ji->image, mono_metadata_token_index (ji->token));
6656                         MONO_INST_NEW (cfg, ins, OP_OBJC_GET_SELECTOR);
6657                         ins->dreg = mono_alloc_ireg (cfg);
6658                         // FIXME: Leaks
6659                         ins->inst_p0 = mono_string_to_utf8 (s);
6660                         MONO_ADD_INS (cfg->cbb, ins);
6661                         return ins;
6662                 }
6663         }
6664
6665 #ifdef MONO_ARCH_SIMD_INTRINSICS
6666         if (cfg->opt & MONO_OPT_SIMD) {
6667                 ins = mono_emit_simd_intrinsics (cfg, cmethod, fsig, args);
6668                 if (ins)
6669                         return ins;
6670         }
6671 #endif
6672
6673         ins = mono_emit_native_types_intrinsics (cfg, cmethod, fsig, args);
6674         if (ins)
6675                 return ins;
6676
6677         if (COMPILE_LLVM (cfg)) {
6678                 ins = llvm_emit_inst_for_method (cfg, cmethod, fsig, args);
6679                 if (ins)
6680                         return ins;
6681         }
6682
6683         return mono_arch_emit_inst_for_method (cfg, cmethod, fsig, args);
6684 }
6685
6686 /*
6687  * This entry point could be used later for arbitrary method
6688  * redirection.
6689  */
6690 inline static MonoInst*
6691 mini_redirect_call (MonoCompile *cfg, MonoMethod *method,  
6692                                         MonoMethodSignature *signature, MonoInst **args, MonoInst *this_ins)
6693 {
6694         if (method->klass == mono_defaults.string_class) {
6695                 /* managed string allocation support */
6696                 if (strcmp (method->name, "InternalAllocateStr") == 0 && !(mono_profiler_events & MONO_PROFILE_ALLOCATIONS) && !(cfg->opt & MONO_OPT_SHARED)) {
6697                         MonoInst *iargs [2];
6698                         MonoVTable *vtable = mono_class_vtable (cfg->domain, method->klass);
6699                         MonoMethod *managed_alloc = NULL;
6700
6701                         g_assert (vtable); /*Should not fail since it System.String*/
6702 #ifndef MONO_CROSS_COMPILE
6703                         managed_alloc = mono_gc_get_managed_allocator (method->klass, FALSE, FALSE);
6704 #endif
6705                         if (!managed_alloc)
6706                                 return NULL;
6707                         EMIT_NEW_VTABLECONST (cfg, iargs [0], vtable);
6708                         iargs [1] = args [0];
6709                         return mono_emit_method_call (cfg, managed_alloc, iargs, this_ins);
6710                 }
6711         }
6712         return NULL;
6713 }
6714
6715 static void
6716 mono_save_args (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **sp)
6717 {
6718         MonoInst *store, *temp;
6719         int i;
6720
6721         for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
6722                 MonoType *argtype = (sig->hasthis && (i == 0)) ? type_from_stack_type (*sp) : sig->params [i - sig->hasthis];
6723
6724                 /*
6725                  * FIXME: We should use *args++ = sp [0], but that would mean the arg
6726                  * would be different than the MonoInst's used to represent arguments, and
6727                  * the ldelema implementation can't deal with that.
6728                  * Solution: When ldelema is used on an inline argument, create a var for 
6729                  * it, emit ldelema on that var, and emit the saving code below in
6730                  * inline_method () if needed.
6731                  */
6732                 temp = mono_compile_create_var (cfg, argtype, OP_LOCAL);
6733                 cfg->args [i] = temp;
6734                 /* This uses cfg->args [i] which is set by the preceeding line */
6735                 EMIT_NEW_ARGSTORE (cfg, store, i, *sp);
6736                 store->cil_code = sp [0]->cil_code;
6737                 sp++;
6738         }
6739 }
6740
6741 #define MONO_INLINE_CALLED_LIMITED_METHODS 1
6742 #define MONO_INLINE_CALLER_LIMITED_METHODS 1
6743
6744 #if (MONO_INLINE_CALLED_LIMITED_METHODS)
6745 static gboolean
6746 check_inline_called_method_name_limit (MonoMethod *called_method)
6747 {
6748         int strncmp_result;
6749         static const char *limit = NULL;
6750         
6751         if (limit == NULL) {
6752                 const char *limit_string = g_getenv ("MONO_INLINE_CALLED_METHOD_NAME_LIMIT");
6753
6754                 if (limit_string != NULL)
6755                         limit = limit_string;
6756                 else
6757                         limit = "";
6758         }
6759
6760         if (limit [0] != '\0') {
6761                 char *called_method_name = mono_method_full_name (called_method, TRUE);
6762
6763                 strncmp_result = strncmp (called_method_name, limit, strlen (limit));
6764                 g_free (called_method_name);
6765         
6766                 //return (strncmp_result <= 0);
6767                 return (strncmp_result == 0);
6768         } else {
6769                 return TRUE;
6770         }
6771 }
6772 #endif
6773
6774 #if (MONO_INLINE_CALLER_LIMITED_METHODS)
6775 static gboolean
6776 check_inline_caller_method_name_limit (MonoMethod *caller_method)
6777 {
6778         int strncmp_result;
6779         static const char *limit = NULL;
6780         
6781         if (limit == NULL) {
6782                 const char *limit_string = g_getenv ("MONO_INLINE_CALLER_METHOD_NAME_LIMIT");
6783                 if (limit_string != NULL) {
6784                         limit = limit_string;
6785                 } else {
6786                         limit = "";
6787                 }
6788         }
6789
6790         if (limit [0] != '\0') {
6791                 char *caller_method_name = mono_method_full_name (caller_method, TRUE);
6792
6793                 strncmp_result = strncmp (caller_method_name, limit, strlen (limit));
6794                 g_free (caller_method_name);
6795         
6796                 //return (strncmp_result <= 0);
6797                 return (strncmp_result == 0);
6798         } else {
6799                 return TRUE;
6800         }
6801 }
6802 #endif
6803
6804 static void
6805 emit_init_rvar (MonoCompile *cfg, int dreg, MonoType *rtype)
6806 {
6807         static double r8_0 = 0.0;
6808         static float r4_0 = 0.0;
6809         MonoInst *ins;
6810         int t;
6811
6812         rtype = mini_get_underlying_type (rtype);
6813         t = rtype->type;
6814
6815         if (rtype->byref) {
6816                 MONO_EMIT_NEW_PCONST (cfg, dreg, NULL);
6817         } else if (t >= MONO_TYPE_BOOLEAN && t <= MONO_TYPE_U4) {
6818                 MONO_EMIT_NEW_ICONST (cfg, dreg, 0);
6819         } else if (t == MONO_TYPE_I8 || t == MONO_TYPE_U8) {
6820                 MONO_EMIT_NEW_I8CONST (cfg, dreg, 0);
6821         } else if (cfg->r4fp && t == MONO_TYPE_R4) {
6822                 MONO_INST_NEW (cfg, ins, OP_R4CONST);
6823                 ins->type = STACK_R4;
6824                 ins->inst_p0 = (void*)&r4_0;
6825                 ins->dreg = dreg;
6826                 MONO_ADD_INS (cfg->cbb, ins);
6827         } else if (t == MONO_TYPE_R4 || t == MONO_TYPE_R8) {
6828                 MONO_INST_NEW (cfg, ins, OP_R8CONST);
6829                 ins->type = STACK_R8;
6830                 ins->inst_p0 = (void*)&r8_0;
6831                 ins->dreg = dreg;
6832                 MONO_ADD_INS (cfg->cbb, ins);
6833         } else if ((t == MONO_TYPE_VALUETYPE) || (t == MONO_TYPE_TYPEDBYREF) ||
6834                    ((t == MONO_TYPE_GENERICINST) && mono_type_generic_inst_is_valuetype (rtype))) {
6835                 MONO_EMIT_NEW_VZERO (cfg, dreg, mono_class_from_mono_type (rtype));
6836         } else if (((t == MONO_TYPE_VAR) || (t == MONO_TYPE_MVAR)) && mini_type_var_is_vt (rtype)) {
6837                 MONO_EMIT_NEW_VZERO (cfg, dreg, mono_class_from_mono_type (rtype));
6838         } else {
6839                 MONO_EMIT_NEW_PCONST (cfg, dreg, NULL);
6840         }
6841 }
6842
6843 static void
6844 emit_dummy_init_rvar (MonoCompile *cfg, int dreg, MonoType *rtype)
6845 {
6846         int t;
6847
6848         rtype = mini_get_underlying_type (rtype);
6849         t = rtype->type;
6850
6851         if (rtype->byref) {
6852                 MONO_EMIT_NEW_DUMMY_INIT (cfg, dreg, OP_DUMMY_PCONST);
6853         } else if (t >= MONO_TYPE_BOOLEAN && t <= MONO_TYPE_U4) {
6854                 MONO_EMIT_NEW_DUMMY_INIT (cfg, dreg, OP_DUMMY_ICONST);
6855         } else if (t == MONO_TYPE_I8 || t == MONO_TYPE_U8) {
6856                 MONO_EMIT_NEW_DUMMY_INIT (cfg, dreg, OP_DUMMY_I8CONST);
6857         } else if (cfg->r4fp && t == MONO_TYPE_R4) {
6858                 MONO_EMIT_NEW_DUMMY_INIT (cfg, dreg, OP_DUMMY_R4CONST);
6859         } else if (t == MONO_TYPE_R4 || t == MONO_TYPE_R8) {
6860                 MONO_EMIT_NEW_DUMMY_INIT (cfg, dreg, OP_DUMMY_R8CONST);
6861         } else if ((t == MONO_TYPE_VALUETYPE) || (t == MONO_TYPE_TYPEDBYREF) ||
6862                    ((t == MONO_TYPE_GENERICINST) && mono_type_generic_inst_is_valuetype (rtype))) {
6863                 MONO_EMIT_NEW_DUMMY_INIT (cfg, dreg, OP_DUMMY_VZERO);
6864         } else if (((t == MONO_TYPE_VAR) || (t == MONO_TYPE_MVAR)) && mini_type_var_is_vt (rtype)) {
6865                 MONO_EMIT_NEW_DUMMY_INIT (cfg, dreg, OP_DUMMY_VZERO);
6866         } else {
6867                 emit_init_rvar (cfg, dreg, rtype);
6868         }
6869 }
6870
6871 /* If INIT is FALSE, emit dummy initialization statements to keep the IR valid */
6872 static void
6873 emit_init_local (MonoCompile *cfg, int local, MonoType *type, gboolean init)
6874 {
6875         MonoInst *var = cfg->locals [local];
6876         if (COMPILE_SOFT_FLOAT (cfg)) {
6877                 MonoInst *store;
6878                 int reg = alloc_dreg (cfg, var->type);
6879                 emit_init_rvar (cfg, reg, type);
6880                 EMIT_NEW_LOCSTORE (cfg, store, local, cfg->cbb->last_ins);
6881         } else {
6882                 if (init)
6883                         emit_init_rvar (cfg, var->dreg, type);
6884                 else
6885                         emit_dummy_init_rvar (cfg, var->dreg, type);
6886         }
6887 }
6888
6889 /*
6890  * inline_method:
6891  *
6892  *   Return the cost of inlining CMETHOD.
6893  */
6894 static int
6895 inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **sp,
6896                            guchar *ip, guint real_offset, gboolean inline_always)
6897 {
6898         MonoInst *ins, *rvar = NULL;
6899         MonoMethodHeader *cheader;
6900         MonoBasicBlock *ebblock, *sbblock;
6901         int i, costs;
6902         MonoMethod *prev_inlined_method;
6903         MonoInst **prev_locals, **prev_args;
6904         MonoType **prev_arg_types;
6905         guint prev_real_offset;
6906         GHashTable *prev_cbb_hash;
6907         MonoBasicBlock **prev_cil_offset_to_bb;
6908         MonoBasicBlock *prev_cbb;
6909         unsigned char* prev_cil_start;
6910         guint32 prev_cil_offset_to_bb_len;
6911         MonoMethod *prev_current_method;
6912         MonoGenericContext *prev_generic_context;
6913         gboolean ret_var_set, prev_ret_var_set, prev_disable_inline, virtual = FALSE;
6914
6915         g_assert (cfg->exception_type == MONO_EXCEPTION_NONE);
6916
6917 #if (MONO_INLINE_CALLED_LIMITED_METHODS)
6918         if ((! inline_always) && ! check_inline_called_method_name_limit (cmethod))
6919                 return 0;
6920 #endif
6921 #if (MONO_INLINE_CALLER_LIMITED_METHODS)
6922         if ((! inline_always) && ! check_inline_caller_method_name_limit (cfg->method))
6923                 return 0;
6924 #endif
6925
6926         if (!fsig)
6927                 fsig = mono_method_signature (cmethod);
6928
6929         if (cfg->verbose_level > 2)
6930                 printf ("INLINE START %p %s -> %s\n", cmethod,  mono_method_full_name (cfg->method, TRUE), mono_method_full_name (cmethod, TRUE));
6931
6932         if (!cmethod->inline_info) {
6933                 cfg->stat_inlineable_methods++;
6934                 cmethod->inline_info = 1;
6935         }
6936
6937         /* allocate local variables */
6938         cheader = mono_method_get_header (cmethod);
6939
6940         if (cheader == NULL || mono_loader_get_last_error ()) {
6941                 MonoLoaderError *error = mono_loader_get_last_error ();
6942
6943                 if (cheader)
6944                         mono_metadata_free_mh (cheader);
6945                 if (inline_always && error)
6946                         mono_cfg_set_exception (cfg, error->exception_type);
6947
6948                 mono_loader_clear_error ();
6949                 return 0;
6950         }
6951
6952         /*Must verify before creating locals as it can cause the JIT to assert.*/
6953         if (mono_compile_is_broken (cfg, cmethod, FALSE)) {
6954                 mono_metadata_free_mh (cheader);
6955                 return 0;
6956         }
6957
6958         /* allocate space to store the return value */
6959         if (!MONO_TYPE_IS_VOID (fsig->ret)) {
6960                 rvar = mono_compile_create_var (cfg, fsig->ret, OP_LOCAL);
6961         }
6962
6963         prev_locals = cfg->locals;
6964         cfg->locals = mono_mempool_alloc0 (cfg->mempool, cheader->num_locals * sizeof (MonoInst*));     
6965         for (i = 0; i < cheader->num_locals; ++i)
6966                 cfg->locals [i] = mono_compile_create_var (cfg, cheader->locals [i], OP_LOCAL);
6967
6968         /* allocate start and end blocks */
6969         /* This is needed so if the inline is aborted, we can clean up */
6970         NEW_BBLOCK (cfg, sbblock);
6971         sbblock->real_offset = real_offset;
6972
6973         NEW_BBLOCK (cfg, ebblock);
6974         ebblock->block_num = cfg->num_bblocks++;
6975         ebblock->real_offset = real_offset;
6976
6977         prev_args = cfg->args;
6978         prev_arg_types = cfg->arg_types;
6979         prev_inlined_method = cfg->inlined_method;
6980         cfg->inlined_method = cmethod;
6981         cfg->ret_var_set = FALSE;
6982         cfg->inline_depth ++;
6983         prev_real_offset = cfg->real_offset;
6984         prev_cbb_hash = cfg->cbb_hash;
6985         prev_cil_offset_to_bb = cfg->cil_offset_to_bb;
6986         prev_cil_offset_to_bb_len = cfg->cil_offset_to_bb_len;
6987         prev_cil_start = cfg->cil_start;
6988         prev_cbb = cfg->cbb;
6989         prev_current_method = cfg->current_method;
6990         prev_generic_context = cfg->generic_context;
6991         prev_ret_var_set = cfg->ret_var_set;
6992         prev_disable_inline = cfg->disable_inline;
6993
6994         if (ip && *ip == CEE_CALLVIRT && !(cmethod->flags & METHOD_ATTRIBUTE_STATIC))
6995                 virtual = TRUE;
6996
6997         costs = mono_method_to_ir (cfg, cmethod, sbblock, ebblock, rvar, sp, real_offset, virtual);
6998
6999         ret_var_set = cfg->ret_var_set;
7000
7001         cfg->inlined_method = prev_inlined_method;
7002         cfg->real_offset = prev_real_offset;
7003         cfg->cbb_hash = prev_cbb_hash;
7004         cfg->cil_offset_to_bb = prev_cil_offset_to_bb;
7005         cfg->cil_offset_to_bb_len = prev_cil_offset_to_bb_len;
7006         cfg->cil_start = prev_cil_start;
7007         cfg->locals = prev_locals;
7008         cfg->args = prev_args;
7009         cfg->arg_types = prev_arg_types;
7010         cfg->current_method = prev_current_method;
7011         cfg->generic_context = prev_generic_context;
7012         cfg->ret_var_set = prev_ret_var_set;
7013         cfg->disable_inline = prev_disable_inline;
7014         cfg->inline_depth --;
7015
7016         if ((costs >= 0 && costs < 60) || inline_always || (costs >= 0 && (cmethod->iflags & METHOD_IMPL_ATTRIBUTE_AGGRESSIVE_INLINING))) {
7017                 if (cfg->verbose_level > 2)
7018                         printf ("INLINE END %s -> %s\n", mono_method_full_name (cfg->method, TRUE), mono_method_full_name (cmethod, TRUE));
7019                 
7020                 cfg->stat_inlined_methods++;
7021
7022                 /* always add some code to avoid block split failures */
7023                 MONO_INST_NEW (cfg, ins, OP_NOP);
7024                 MONO_ADD_INS (prev_cbb, ins);
7025
7026                 prev_cbb->next_bb = sbblock;
7027                 link_bblock (cfg, prev_cbb, sbblock);
7028
7029                 /* 
7030                  * Get rid of the begin and end bblocks if possible to aid local
7031                  * optimizations.
7032                  */
7033                 mono_merge_basic_blocks (cfg, prev_cbb, sbblock);
7034
7035                 if ((prev_cbb->out_count == 1) && (prev_cbb->out_bb [0]->in_count == 1) && (prev_cbb->out_bb [0] != ebblock))
7036                         mono_merge_basic_blocks (cfg, prev_cbb, prev_cbb->out_bb [0]);
7037
7038                 if ((ebblock->in_count == 1) && ebblock->in_bb [0]->out_count == 1) {
7039                         MonoBasicBlock *prev = ebblock->in_bb [0];
7040                         mono_merge_basic_blocks (cfg, prev, ebblock);
7041                         cfg->cbb = prev;
7042                         if ((prev_cbb->out_count == 1) && (prev_cbb->out_bb [0]->in_count == 1) && (prev_cbb->out_bb [0] == prev)) {
7043                                 mono_merge_basic_blocks (cfg, prev_cbb, prev);
7044                                 cfg->cbb = prev_cbb;
7045                         }
7046                 } else {
7047                         /* 
7048                          * Its possible that the rvar is set in some prev bblock, but not in others.
7049                          * (#1835).
7050                          */
7051                         if (rvar) {
7052                                 MonoBasicBlock *bb;
7053
7054                                 for (i = 0; i < ebblock->in_count; ++i) {
7055                                         bb = ebblock->in_bb [i];
7056
7057                                         if (bb->last_ins && bb->last_ins->opcode == OP_NOT_REACHED) {
7058                                                 cfg->cbb = bb;
7059
7060                                                 emit_init_rvar (cfg, rvar->dreg, fsig->ret);
7061                                         }
7062                                 }
7063                         }
7064
7065                         cfg->cbb = ebblock;
7066                 }
7067
7068                 if (rvar) {
7069                         /*
7070                          * If the inlined method contains only a throw, then the ret var is not 
7071                          * set, so set it to a dummy value.
7072                          */
7073                         if (!ret_var_set)
7074                                 emit_init_rvar (cfg, rvar->dreg, fsig->ret);
7075
7076                         EMIT_NEW_TEMPLOAD (cfg, ins, rvar->inst_c0);
7077                         *sp++ = ins;
7078                 }
7079                 cfg->headers_to_free = g_slist_prepend_mempool (cfg->mempool, cfg->headers_to_free, cheader);
7080                 return costs + 1;
7081         } else {
7082                 if (cfg->verbose_level > 2)
7083                         printf ("INLINE ABORTED %s (cost %d)\n", mono_method_full_name (cmethod, TRUE), costs);
7084                 cfg->exception_type = MONO_EXCEPTION_NONE;
7085                 mono_loader_clear_error ();
7086
7087                 /* This gets rid of the newly added bblocks */
7088                 cfg->cbb = prev_cbb;
7089         }
7090         cfg->headers_to_free = g_slist_prepend_mempool (cfg->mempool, cfg->headers_to_free, cheader);
7091         return 0;
7092 }
7093
7094 /*
7095  * Some of these comments may well be out-of-date.
7096  * Design decisions: we do a single pass over the IL code (and we do bblock 
7097  * splitting/merging in the few cases when it's required: a back jump to an IL
7098  * address that was not already seen as bblock starting point).
7099  * Code is validated as we go (full verification is still better left to metadata/verify.c).
7100  * Complex operations are decomposed in simpler ones right away. We need to let the 
7101  * arch-specific code peek and poke inside this process somehow (except when the 
7102  * optimizations can take advantage of the full semantic info of coarse opcodes).
7103  * All the opcodes of the form opcode.s are 'normalized' to opcode.
7104  * MonoInst->opcode initially is the IL opcode or some simplification of that 
7105  * (OP_LOAD, OP_STORE). The arch-specific code may rearrange it to an arch-specific 
7106  * opcode with value bigger than OP_LAST.
7107  * At this point the IR can be handed over to an interpreter, a dumb code generator
7108  * or to the optimizing code generator that will translate it to SSA form.
7109  *
7110  * Profiling directed optimizations.
7111  * We may compile by default with few or no optimizations and instrument the code
7112  * or the user may indicate what methods to optimize the most either in a config file
7113  * or through repeated runs where the compiler applies offline the optimizations to 
7114  * each method and then decides if it was worth it.
7115  */
7116
7117 #define CHECK_TYPE(ins) if (!(ins)->type) UNVERIFIED
7118 #define CHECK_STACK(num) if ((sp - stack_start) < (num)) UNVERIFIED
7119 #define CHECK_STACK_OVF(num) if (((sp - stack_start) + (num)) > header->max_stack) UNVERIFIED
7120 #define CHECK_ARG(num) if ((unsigned)(num) >= (unsigned)num_args) UNVERIFIED
7121 #define CHECK_LOCAL(num) if ((unsigned)(num) >= (unsigned)header->num_locals) UNVERIFIED
7122 #define CHECK_OPSIZE(size) if (ip + size > end) UNVERIFIED
7123 #define CHECK_UNVERIFIABLE(cfg) if (cfg->unverifiable) UNVERIFIED
7124 #define CHECK_TYPELOAD(klass) if (!(klass) || (klass)->exception_type) TYPE_LOAD_ERROR ((klass))
7125
7126 /* offset from br.s -> br like opcodes */
7127 #define BIG_BRANCH_OFFSET 13
7128
7129 static gboolean
7130 ip_in_bb (MonoCompile *cfg, MonoBasicBlock *bb, const guint8* ip)
7131 {
7132         MonoBasicBlock *b = cfg->cil_offset_to_bb [ip - cfg->cil_start];
7133
7134         return b == NULL || b == bb;
7135 }
7136
7137 static int
7138 get_basic_blocks (MonoCompile *cfg, MonoMethodHeader* header, guint real_offset, unsigned char *start, unsigned char *end, unsigned char **pos)
7139 {
7140         unsigned char *ip = start;
7141         unsigned char *target;
7142         int i;
7143         guint cli_addr;
7144         MonoBasicBlock *bblock;
7145         const MonoOpcode *opcode;
7146
7147         while (ip < end) {
7148                 cli_addr = ip - start;
7149                 i = mono_opcode_value ((const guint8 **)&ip, end);
7150                 if (i < 0)
7151                         UNVERIFIED;
7152                 opcode = &mono_opcodes [i];
7153                 switch (opcode->argument) {
7154                 case MonoInlineNone:
7155                         ip++; 
7156                         break;
7157                 case MonoInlineString:
7158                 case MonoInlineType:
7159                 case MonoInlineField:
7160                 case MonoInlineMethod:
7161                 case MonoInlineTok:
7162                 case MonoInlineSig:
7163                 case MonoShortInlineR:
7164                 case MonoInlineI:
7165                         ip += 5;
7166                         break;
7167                 case MonoInlineVar:
7168                         ip += 3;
7169                         break;
7170                 case MonoShortInlineVar:
7171                 case MonoShortInlineI:
7172                         ip += 2;
7173                         break;
7174                 case MonoShortInlineBrTarget:
7175                         target = start + cli_addr + 2 + (signed char)ip [1];
7176                         GET_BBLOCK (cfg, bblock, target);
7177                         ip += 2;
7178                         if (ip < end)
7179                                 GET_BBLOCK (cfg, bblock, ip);
7180                         break;
7181                 case MonoInlineBrTarget:
7182                         target = start + cli_addr + 5 + (gint32)read32 (ip + 1);
7183                         GET_BBLOCK (cfg, bblock, target);
7184                         ip += 5;
7185                         if (ip < end)
7186                                 GET_BBLOCK (cfg, bblock, ip);
7187                         break;
7188                 case MonoInlineSwitch: {
7189                         guint32 n = read32 (ip + 1);
7190                         guint32 j;
7191                         ip += 5;
7192                         cli_addr += 5 + 4 * n;
7193                         target = start + cli_addr;
7194                         GET_BBLOCK (cfg, bblock, target);
7195                         
7196                         for (j = 0; j < n; ++j) {
7197                                 target = start + cli_addr + (gint32)read32 (ip);
7198                                 GET_BBLOCK (cfg, bblock, target);
7199                                 ip += 4;
7200                         }
7201                         break;
7202                 }
7203                 case MonoInlineR:
7204                 case MonoInlineI8:
7205                         ip += 9;
7206                         break;
7207                 default:
7208                         g_assert_not_reached ();
7209                 }
7210
7211                 if (i == CEE_THROW) {
7212                         unsigned char *bb_start = ip - 1;
7213                         
7214                         /* Find the start of the bblock containing the throw */
7215                         bblock = NULL;
7216                         while ((bb_start >= start) && !bblock) {
7217                                 bblock = cfg->cil_offset_to_bb [(bb_start) - start];
7218                                 bb_start --;
7219                         }
7220                         if (bblock)
7221                                 bblock->out_of_line = 1;
7222                 }
7223         }
7224         return 0;
7225 unverified:
7226 exception_exit:
7227         *pos = ip;
7228         return 1;
7229 }
7230
7231 static inline MonoMethod *
7232 mini_get_method_allow_open (MonoMethod *m, guint32 token, MonoClass *klass, MonoGenericContext *context)
7233 {
7234         MonoMethod *method;
7235
7236         if (m->wrapper_type != MONO_WRAPPER_NONE) {
7237                 method = mono_method_get_wrapper_data (m, token);
7238                 if (context) {
7239                         MonoError error;
7240                         method = mono_class_inflate_generic_method_checked (method, context, &error);
7241                         g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
7242                 }
7243         } else {
7244                 method = mono_get_method_full (m->klass->image, token, klass, context);
7245         }
7246
7247         return method;
7248 }
7249
7250 static inline MonoMethod *
7251 mini_get_method (MonoCompile *cfg, MonoMethod *m, guint32 token, MonoClass *klass, MonoGenericContext *context)
7252 {
7253         MonoMethod *method = mini_get_method_allow_open (m, token, klass, context);
7254
7255         if (method && cfg && !cfg->gshared && mono_class_is_open_constructed_type (&method->klass->byval_arg))
7256                 return NULL;
7257
7258         return method;
7259 }
7260
7261 static inline MonoClass*
7262 mini_get_class (MonoMethod *method, guint32 token, MonoGenericContext *context)
7263 {
7264         MonoError error;
7265         MonoClass *klass;
7266
7267         if (method->wrapper_type != MONO_WRAPPER_NONE) {
7268                 klass = mono_method_get_wrapper_data (method, token);
7269                 if (context)
7270                         klass = mono_class_inflate_generic_class (klass, context);
7271         } else {
7272                 klass = mono_class_get_and_inflate_typespec_checked (method->klass->image, token, context, &error);
7273                 mono_error_cleanup (&error); /* FIXME don't swallow the error */
7274         }
7275         if (klass)
7276                 mono_class_init (klass);
7277         return klass;
7278 }
7279
7280 static inline MonoMethodSignature*
7281 mini_get_signature (MonoMethod *method, guint32 token, MonoGenericContext *context)
7282 {
7283         MonoMethodSignature *fsig;
7284
7285         if (method->wrapper_type != MONO_WRAPPER_NONE) {
7286                 fsig = (MonoMethodSignature *)mono_method_get_wrapper_data (method, token);
7287         } else {
7288                 fsig = mono_metadata_parse_signature (method->klass->image, token);
7289         }
7290         if (context) {
7291                 MonoError error;
7292                 fsig = mono_inflate_generic_signature(fsig, context, &error);
7293                 // FIXME:
7294                 g_assert(mono_error_ok(&error));
7295         }
7296         return fsig;
7297 }
7298
7299 static MonoMethod*
7300 throw_exception (void)
7301 {
7302         static MonoMethod *method = NULL;
7303
7304         if (!method) {
7305                 MonoSecurityManager *secman = mono_security_manager_get_methods ();
7306                 method = mono_class_get_method_from_name (secman->securitymanager, "ThrowException", 1);
7307         }
7308         g_assert (method);
7309         return method;
7310 }
7311
7312 static void
7313 emit_throw_exception (MonoCompile *cfg, MonoException *ex)
7314 {
7315         MonoMethod *thrower = throw_exception ();
7316         MonoInst *args [1];
7317
7318         EMIT_NEW_PCONST (cfg, args [0], ex);
7319         mono_emit_method_call (cfg, thrower, args, NULL);
7320 }
7321
7322 /*
7323  * Return the original method is a wrapper is specified. We can only access 
7324  * the custom attributes from the original method.
7325  */
7326 static MonoMethod*
7327 get_original_method (MonoMethod *method)
7328 {
7329         if (method->wrapper_type == MONO_WRAPPER_NONE)
7330                 return method;
7331
7332         /* native code (which is like Critical) can call any managed method XXX FIXME XXX to validate all usages */
7333         if (method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED)
7334                 return NULL;
7335
7336         /* in other cases we need to find the original method */
7337         return mono_marshal_method_from_wrapper (method);
7338 }
7339
7340 static void
7341 ensure_method_is_allowed_to_access_field (MonoCompile *cfg, MonoMethod *caller, MonoClassField *field)
7342 {
7343         /* we can't get the coreclr security level on wrappers since they don't have the attributes */
7344         MonoException *ex = mono_security_core_clr_is_field_access_allowed (get_original_method (caller), field);
7345         if (ex)
7346                 emit_throw_exception (cfg, ex);
7347 }
7348
7349 static void
7350 ensure_method_is_allowed_to_call_method (MonoCompile *cfg, MonoMethod *caller, MonoMethod *callee)
7351 {
7352         /* we can't get the coreclr security level on wrappers since they don't have the attributes */
7353         MonoException *ex = mono_security_core_clr_is_call_allowed (get_original_method (caller), callee);
7354         if (ex)
7355                 emit_throw_exception (cfg, ex);
7356 }
7357
7358 /*
7359  * Check that the IL instructions at ip are the array initialization
7360  * sequence and return the pointer to the data and the size.
7361  */
7362 static const char*
7363 initialize_array_data (MonoMethod *method, gboolean aot, unsigned char *ip, MonoClass *klass, guint32 len, int *out_size, guint32 *out_field_token)
7364 {
7365         /*
7366          * newarr[System.Int32]
7367          * dup
7368          * ldtoken field valuetype ...
7369          * call void class [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype [mscorlib]System.RuntimeFieldHandle)
7370          */
7371         if (ip [0] == CEE_DUP && ip [1] == CEE_LDTOKEN && ip [5] == 0x4 && ip [6] == CEE_CALL) {
7372                 MonoError error;
7373                 guint32 token = read32 (ip + 7);
7374                 guint32 field_token = read32 (ip + 2);
7375                 guint32 field_index = field_token & 0xffffff;
7376                 guint32 rva;
7377                 const char *data_ptr;
7378                 int size = 0;
7379                 MonoMethod *cmethod;
7380                 MonoClass *dummy_class;
7381                 MonoClassField *field = mono_field_from_token_checked (method->klass->image, field_token, &dummy_class, NULL, &error);
7382                 int dummy_align;
7383
7384                 if (!field) {
7385                         mono_error_cleanup (&error); /* FIXME don't swallow the error */
7386                         return NULL;
7387                 }
7388
7389                 *out_field_token = field_token;
7390
7391                 cmethod = mini_get_method (NULL, method, token, NULL, NULL);
7392                 if (!cmethod)
7393                         return NULL;
7394                 if (strcmp (cmethod->name, "InitializeArray") || strcmp (cmethod->klass->name, "RuntimeHelpers") || cmethod->klass->image != mono_defaults.corlib)
7395                         return NULL;
7396                 switch (mono_type_get_underlying_type (&klass->byval_arg)->type) {
7397                 case MONO_TYPE_BOOLEAN:
7398                 case MONO_TYPE_I1:
7399                 case MONO_TYPE_U1:
7400                         size = 1; break;
7401                 /* we need to swap on big endian, so punt. Should we handle R4 and R8 as well? */
7402 #if TARGET_BYTE_ORDER == G_LITTLE_ENDIAN
7403                 case MONO_TYPE_CHAR:
7404                 case MONO_TYPE_I2:
7405                 case MONO_TYPE_U2:
7406                         size = 2; break;
7407                 case MONO_TYPE_I4:
7408                 case MONO_TYPE_U4:
7409                 case MONO_TYPE_R4:
7410                         size = 4; break;
7411                 case MONO_TYPE_R8:
7412                 case MONO_TYPE_I8:
7413                 case MONO_TYPE_U8:
7414                         size = 8; break;
7415 #endif
7416                 default:
7417                         return NULL;
7418                 }
7419                 size *= len;
7420                 if (size > mono_type_size (field->type, &dummy_align))
7421                     return NULL;
7422                 *out_size = size;
7423                 /*g_print ("optimized in %s: size: %d, numelems: %d\n", method->name, size, newarr->inst_newa_len->inst_c0);*/
7424                 if (!image_is_dynamic (method->klass->image)) {
7425                         field_index = read32 (ip + 2) & 0xffffff;
7426                         mono_metadata_field_info (method->klass->image, field_index - 1, NULL, &rva, NULL);
7427                         data_ptr = mono_image_rva_map (method->klass->image, rva);
7428                         /*g_print ("field: 0x%08x, rva: %d, rva_ptr: %p\n", read32 (ip + 2), rva, data_ptr);*/
7429                         /* for aot code we do the lookup on load */
7430                         if (aot && data_ptr)
7431                                 return GUINT_TO_POINTER (rva);
7432                 } else {
7433                         /*FIXME is it possible to AOT a SRE assembly not meant to be saved? */ 
7434                         g_assert (!aot);
7435                         data_ptr = mono_field_get_data (field);
7436                 }
7437                 return data_ptr;
7438         }
7439         return NULL;
7440 }
7441
7442 static void
7443 set_exception_type_from_invalid_il (MonoCompile *cfg, MonoMethod *method, unsigned char *ip)
7444 {
7445         char *method_fname = mono_method_full_name (method, TRUE);
7446         char *method_code;
7447         MonoMethodHeader *header = mono_method_get_header (method);
7448
7449         if (header->code_size == 0)
7450                 method_code = g_strdup ("method body is empty.");
7451         else
7452                 method_code = mono_disasm_code_one (NULL, method, ip, NULL);
7453         mono_cfg_set_exception (cfg, MONO_EXCEPTION_INVALID_PROGRAM);
7454         cfg->exception_message = g_strdup_printf ("Invalid IL code in %s: %s\n", method_fname, method_code);
7455         g_free (method_fname);
7456         g_free (method_code);
7457         cfg->headers_to_free = g_slist_prepend_mempool (cfg->mempool, cfg->headers_to_free, header);
7458 }
7459
7460 static void
7461 set_exception_object (MonoCompile *cfg, MonoException *exception)
7462 {
7463         mono_cfg_set_exception (cfg, MONO_EXCEPTION_OBJECT_SUPPLIED);
7464         MONO_GC_REGISTER_ROOT_SINGLE (cfg->exception_ptr, MONO_ROOT_SOURCE_JIT, "jit exception");
7465         cfg->exception_ptr = exception;
7466 }
7467
7468 static void
7469 emit_stloc_ir (MonoCompile *cfg, MonoInst **sp, MonoMethodHeader *header, int n)
7470 {
7471         MonoInst *ins;
7472         guint32 opcode = mono_type_to_regmove (cfg, header->locals [n]);
7473         if ((opcode == OP_MOVE) && cfg->cbb->last_ins == sp [0]  &&
7474                         ((sp [0]->opcode == OP_ICONST) || (sp [0]->opcode == OP_I8CONST))) {
7475                 /* Optimize reg-reg moves away */
7476                 /* 
7477                  * Can't optimize other opcodes, since sp[0] might point to
7478                  * the last ins of a decomposed opcode.
7479                  */
7480                 sp [0]->dreg = (cfg)->locals [n]->dreg;
7481         } else {
7482                 EMIT_NEW_LOCSTORE (cfg, ins, n, *sp);
7483         }
7484 }
7485
7486 /*
7487  * ldloca inhibits many optimizations so try to get rid of it in common
7488  * cases.
7489  */
7490 static inline unsigned char *
7491 emit_optimized_ldloca_ir (MonoCompile *cfg, unsigned char *ip, unsigned char *end, int size)
7492 {
7493         int local, token;
7494         MonoClass *klass;
7495         MonoType *type;
7496
7497         if (size == 1) {
7498                 local = ip [1];
7499                 ip += 2;
7500         } else {
7501                 local = read16 (ip + 2);
7502                 ip += 4;
7503         }
7504         
7505         if (ip + 6 < end && (ip [0] == CEE_PREFIX1) && (ip [1] == CEE_INITOBJ) && ip_in_bb (cfg, cfg->cbb, ip + 1)) {
7506                 /* From the INITOBJ case */
7507                 token = read32 (ip + 2);
7508                 klass = mini_get_class (cfg->current_method, token, cfg->generic_context);
7509                 CHECK_TYPELOAD (klass);
7510                 type = mini_get_underlying_type (&klass->byval_arg);
7511                 emit_init_local (cfg, local, type, TRUE);
7512                 return ip + 6;
7513         }
7514  exception_exit:
7515         return NULL;
7516 }
7517
7518 static gboolean
7519 is_exception_class (MonoClass *klass)
7520 {
7521         while (klass) {
7522                 if (klass == mono_defaults.exception_class)
7523                         return TRUE;
7524                 klass = klass->parent;
7525         }
7526         return FALSE;
7527 }
7528
7529 /*
7530  * is_jit_optimizer_disabled:
7531  *
7532  *   Determine whenever M's assembly has a DebuggableAttribute with the
7533  * IsJITOptimizerDisabled flag set.
7534  */
7535 static gboolean
7536 is_jit_optimizer_disabled (MonoMethod *m)
7537 {
7538         MonoAssembly *ass = m->klass->image->assembly;
7539         MonoCustomAttrInfo* attrs;
7540         static MonoClass *klass;
7541         int i;
7542         gboolean val = FALSE;
7543
7544         g_assert (ass);
7545         if (ass->jit_optimizer_disabled_inited)
7546                 return ass->jit_optimizer_disabled;
7547
7548         if (!klass)
7549                 klass = mono_class_from_name (mono_defaults.corlib, "System.Diagnostics", "DebuggableAttribute");
7550         if (!klass) {
7551                 /* Linked away */
7552                 ass->jit_optimizer_disabled = FALSE;
7553                 mono_memory_barrier ();
7554                 ass->jit_optimizer_disabled_inited = TRUE;
7555                 return FALSE;
7556         }
7557
7558         attrs = mono_custom_attrs_from_assembly (ass);
7559         if (attrs) {
7560                 for (i = 0; i < attrs->num_attrs; ++i) {
7561                         MonoCustomAttrEntry *attr = &attrs->attrs [i];
7562                         const gchar *p;
7563                         MonoMethodSignature *sig;
7564
7565                         if (!attr->ctor || attr->ctor->klass != klass)
7566                                 continue;
7567                         /* Decode the attribute. See reflection.c */
7568                         p = (const char*)attr->data;
7569                         g_assert (read16 (p) == 0x0001);
7570                         p += 2;
7571
7572                         // FIXME: Support named parameters
7573                         sig = mono_method_signature (attr->ctor);
7574                         if (sig->param_count != 2 || sig->params [0]->type != MONO_TYPE_BOOLEAN || sig->params [1]->type != MONO_TYPE_BOOLEAN)
7575                                 continue;
7576                         /* Two boolean arguments */
7577                         p ++;
7578                         val = *p;
7579                 }
7580                 mono_custom_attrs_free (attrs);
7581         }
7582
7583         ass->jit_optimizer_disabled = val;
7584         mono_memory_barrier ();
7585         ass->jit_optimizer_disabled_inited = TRUE;
7586
7587         return val;
7588 }
7589
7590 static gboolean
7591 is_supported_tail_call (MonoCompile *cfg, MonoMethod *method, MonoMethod *cmethod, MonoMethodSignature *fsig, int call_opcode)
7592 {
7593         gboolean supported_tail_call;
7594         int i;
7595
7596         supported_tail_call = mono_arch_tail_call_supported (cfg, mono_method_signature (method), mono_method_signature (cmethod));
7597
7598         for (i = 0; i < fsig->param_count; ++i) {
7599                 if (fsig->params [i]->byref || fsig->params [i]->type == MONO_TYPE_PTR || fsig->params [i]->type == MONO_TYPE_FNPTR)
7600                         /* These can point to the current method's stack */
7601                         supported_tail_call = FALSE;
7602         }
7603         if (fsig->hasthis && cmethod->klass->valuetype)
7604                 /* this might point to the current method's stack */
7605                 supported_tail_call = FALSE;
7606         if (cmethod->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
7607                 supported_tail_call = FALSE;
7608         if (cfg->method->save_lmf)
7609                 supported_tail_call = FALSE;
7610         if (cmethod->wrapper_type && cmethod->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD)
7611                 supported_tail_call = FALSE;
7612         if (call_opcode != CEE_CALL)
7613                 supported_tail_call = FALSE;
7614
7615         /* Debugging support */
7616 #if 0
7617         if (supported_tail_call) {
7618                 if (!mono_debug_count ())
7619                         supported_tail_call = FALSE;
7620         }
7621 #endif
7622
7623         return supported_tail_call;
7624 }
7625
7626 /*
7627  * handle_ctor_call:
7628  *
7629  *   Handle calls made to ctors from NEWOBJ opcodes.
7630  */
7631 static void
7632 handle_ctor_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, int context_used,
7633                                   MonoInst **sp, guint8 *ip, int *inline_costs)
7634 {
7635         MonoInst *vtable_arg = NULL, *callvirt_this_arg = NULL, *ins;
7636
7637         if (cmethod->klass->valuetype && mono_class_generic_sharing_enabled (cmethod->klass) &&
7638                                         mono_method_is_generic_sharable (cmethod, TRUE)) {
7639                 if (cmethod->is_inflated && mono_method_get_context (cmethod)->method_inst) {
7640                         mono_class_vtable (cfg->domain, cmethod->klass);
7641                         CHECK_TYPELOAD (cmethod->klass);
7642
7643                         vtable_arg = emit_get_rgctx_method (cfg, context_used,
7644                                                                                                 cmethod, MONO_RGCTX_INFO_METHOD_RGCTX);
7645                 } else {
7646                         if (context_used) {
7647                                 vtable_arg = emit_get_rgctx_klass (cfg, context_used,
7648                                                                                                    cmethod->klass, MONO_RGCTX_INFO_VTABLE);
7649                         } else {
7650                                 MonoVTable *vtable = mono_class_vtable (cfg->domain, cmethod->klass);
7651
7652                                 CHECK_TYPELOAD (cmethod->klass);
7653                                 EMIT_NEW_VTABLECONST (cfg, vtable_arg, vtable);
7654                         }
7655                 }
7656         }
7657
7658         /* Avoid virtual calls to ctors if possible */
7659         if (mono_class_is_marshalbyref (cmethod->klass))
7660                 callvirt_this_arg = sp [0];
7661
7662         if (cmethod && (cfg->opt & MONO_OPT_INTRINS) && (ins = mini_emit_inst_for_ctor (cfg, cmethod, fsig, sp))) {
7663                 g_assert (MONO_TYPE_IS_VOID (fsig->ret));
7664                 CHECK_CFG_EXCEPTION;
7665         } else if ((cfg->opt & MONO_OPT_INLINE) && cmethod && !context_used && !vtable_arg &&
7666                            mono_method_check_inlining (cfg, cmethod) &&
7667                            !mono_class_is_subclass_of (cmethod->klass, mono_defaults.exception_class, FALSE)) {
7668                 int costs;
7669
7670                 if ((costs = inline_method (cfg, cmethod, fsig, sp, ip, cfg->real_offset, FALSE))) {
7671                         cfg->real_offset += 5;
7672
7673                         *inline_costs += costs - 5;
7674                 } else {
7675                         INLINE_FAILURE ("inline failure");
7676                         // FIXME-VT: Clean this up
7677                         if (cfg->gsharedvt && mini_is_gsharedvt_signature (fsig))
7678                                 GSHAREDVT_FAILURE(*ip);
7679                         mono_emit_method_call_full (cfg, cmethod, fsig, FALSE, sp, callvirt_this_arg, NULL, NULL);
7680                 }
7681         } else if (cfg->gsharedvt && mini_is_gsharedvt_signature (fsig)) {
7682                 MonoInst *addr;
7683
7684                 addr = emit_get_rgctx_gsharedvt_call (cfg, context_used, fsig, cmethod, MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE);
7685                 mono_emit_calli (cfg, fsig, sp, addr, NULL, vtable_arg);
7686         } else if (context_used &&
7687                            ((!mono_method_is_generic_sharable_full (cmethod, TRUE, FALSE, FALSE) ||
7688                                  !mono_class_generic_sharing_enabled (cmethod->klass)) || cfg->gsharedvt)) {
7689                 MonoInst *cmethod_addr;
7690
7691                 /* Generic calls made out of gsharedvt methods cannot be patched, so use an indirect call */
7692
7693                 cmethod_addr = emit_get_rgctx_method (cfg, context_used,
7694                                                                                           cmethod, MONO_RGCTX_INFO_GENERIC_METHOD_CODE);
7695
7696                 mono_emit_calli (cfg, fsig, sp, cmethod_addr, NULL, vtable_arg);
7697         } else {
7698                 INLINE_FAILURE ("ctor call");
7699                 ins = mono_emit_method_call_full (cfg, cmethod, fsig, FALSE, sp,
7700                                                                                   callvirt_this_arg, NULL, vtable_arg);
7701         }
7702  exception_exit:
7703         return;
7704 }
7705
7706 static void
7707 emit_setret (MonoCompile *cfg, MonoInst *val)
7708 {
7709         MonoType *ret_type = mini_get_underlying_type (mono_method_signature (cfg->method)->ret);
7710         MonoInst *ins;
7711
7712         if (mini_type_to_stind (cfg, ret_type) == CEE_STOBJ) {
7713                 MonoInst *ret_addr;
7714
7715                 if (!cfg->vret_addr) {
7716                         EMIT_NEW_VARSTORE (cfg, ins, cfg->ret, ret_type, val);
7717                 } else {
7718                         EMIT_NEW_RETLOADA (cfg, ret_addr);
7719
7720                         EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STOREV_MEMBASE, ret_addr->dreg, 0, val->dreg);
7721                         ins->klass = mono_class_from_mono_type (ret_type);
7722                 }
7723         } else {
7724 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
7725                 if (COMPILE_SOFT_FLOAT (cfg) && !ret_type->byref && ret_type->type == MONO_TYPE_R4) {
7726                         MonoInst *iargs [1];
7727                         MonoInst *conv;
7728
7729                         iargs [0] = val;
7730                         conv = mono_emit_jit_icall (cfg, mono_fload_r4_arg, iargs);
7731                         mono_arch_emit_setret (cfg, cfg->method, conv);
7732                 } else {
7733                         mono_arch_emit_setret (cfg, cfg->method, val);
7734                 }
7735 #else
7736                 mono_arch_emit_setret (cfg, cfg->method, val);
7737 #endif
7738         }
7739 }
7740
7741 static MonoMethodSignature*
7742 sig_to_rgctx_sig (MonoMethodSignature *sig)
7743 {
7744         // FIXME: memory allocation
7745         MonoMethodSignature *res;
7746         int i;
7747
7748         res = g_malloc (MONO_SIZEOF_METHOD_SIGNATURE + (sig->param_count + 1) * sizeof (MonoType*));
7749         memcpy (res, sig, MONO_SIZEOF_METHOD_SIGNATURE);
7750         res->param_count = sig->param_count + 1;
7751         for (i = 0; i < sig->param_count; ++i)
7752                 res->params [i] = sig->params [i];
7753         res->params [sig->param_count] = &mono_defaults.int_class->byval_arg;
7754         return res;
7755 }
7756
7757 /*
7758  * mono_method_to_ir:
7759  *
7760  *   Translate the .net IL into linear IR.
7761  */
7762 int
7763 mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_bblock, MonoBasicBlock *end_bblock, 
7764                    MonoInst *return_var, MonoInst **inline_args, 
7765                    guint inline_offset, gboolean is_virtual_call)
7766 {
7767         MonoError error;
7768         MonoInst *ins, **sp, **stack_start;
7769         MonoBasicBlock *tblock = NULL, *init_localsbb = NULL;
7770         MonoSimpleBasicBlock *bb = NULL, *original_bb = NULL;
7771         MonoMethod *cmethod, *method_definition;
7772         MonoInst **arg_array;
7773         MonoMethodHeader *header;
7774         MonoImage *image;
7775         guint32 token, ins_flag;
7776         MonoClass *klass;
7777         MonoClass *constrained_class = NULL;
7778         unsigned char *ip, *end, *target, *err_pos;
7779         MonoMethodSignature *sig;
7780         MonoGenericContext *generic_context = NULL;
7781         MonoGenericContainer *generic_container = NULL;
7782         MonoType **param_types;
7783         int i, n, start_new_bblock, dreg;
7784         int num_calls = 0, inline_costs = 0;
7785         int breakpoint_id = 0;
7786         guint num_args;
7787         GSList *class_inits = NULL;
7788         gboolean dont_verify, dont_verify_stloc, readonly = FALSE;
7789         int context_used;
7790         gboolean init_locals, seq_points, skip_dead_blocks;
7791         gboolean sym_seq_points = FALSE;
7792         MonoDebugMethodInfo *minfo;
7793         MonoBitSet *seq_point_locs = NULL;
7794         MonoBitSet *seq_point_set_locs = NULL;
7795
7796         cfg->disable_inline = is_jit_optimizer_disabled (method);
7797
7798         /* serialization and xdomain stuff may need access to private fields and methods */
7799         dont_verify = method->klass->image->assembly->corlib_internal? TRUE: FALSE;
7800         dont_verify |= method->wrapper_type == MONO_WRAPPER_XDOMAIN_INVOKE;
7801         dont_verify |= method->wrapper_type == MONO_WRAPPER_XDOMAIN_DISPATCH;
7802         dont_verify |= method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE; /* bug #77896 */
7803         dont_verify |= method->wrapper_type == MONO_WRAPPER_COMINTEROP;
7804         dont_verify |= method->wrapper_type == MONO_WRAPPER_COMINTEROP_INVOKE;
7805
7806         /* still some type unsafety issues in marshal wrappers... (unknown is PtrToStructure) */
7807         dont_verify_stloc = method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE;
7808         dont_verify_stloc |= method->wrapper_type == MONO_WRAPPER_UNKNOWN;
7809         dont_verify_stloc |= method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED;
7810         dont_verify_stloc |= method->wrapper_type == MONO_WRAPPER_STELEMREF;
7811
7812         image = method->klass->image;
7813         header = mono_method_get_header (method);
7814         if (!header) {
7815                 MonoLoaderError *error;
7816
7817                 if ((error = mono_loader_get_last_error ())) {
7818                         mono_cfg_set_exception (cfg, error->exception_type);
7819                 } else {
7820                         mono_cfg_set_exception (cfg, MONO_EXCEPTION_INVALID_PROGRAM);
7821                         cfg->exception_message = g_strdup_printf ("Missing or incorrect header for method %s", cfg->method->name);
7822                 }
7823                 goto exception_exit;
7824         }
7825         generic_container = mono_method_get_generic_container (method);
7826         sig = mono_method_signature (method);
7827         num_args = sig->hasthis + sig->param_count;
7828         ip = (unsigned char*)header->code;
7829         cfg->cil_start = ip;
7830         end = ip + header->code_size;
7831         cfg->stat_cil_code_size += header->code_size;
7832
7833         seq_points = cfg->gen_seq_points && cfg->method == method;
7834
7835         if (method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
7836                 /* We could hit a seq point before attaching to the JIT (#8338) */
7837                 seq_points = FALSE;
7838         }
7839
7840         if (cfg->gen_sdb_seq_points && cfg->method == method) {
7841                 minfo = mono_debug_lookup_method (method);
7842                 if (minfo) {
7843                         MonoSymSeqPoint *sps;
7844                         int i, n_il_offsets;
7845
7846                         mono_debug_get_seq_points (minfo, NULL, NULL, NULL, &sps, &n_il_offsets);
7847                         seq_point_locs = mono_bitset_mem_new (mono_mempool_alloc0 (cfg->mempool, mono_bitset_alloc_size (header->code_size, 0)), header->code_size, 0);
7848                         seq_point_set_locs = mono_bitset_mem_new (mono_mempool_alloc0 (cfg->mempool, mono_bitset_alloc_size (header->code_size, 0)), header->code_size, 0);
7849                         sym_seq_points = TRUE;
7850                         for (i = 0; i < n_il_offsets; ++i) {
7851                                 if (sps [i].il_offset < header->code_size)
7852                                         mono_bitset_set_fast (seq_point_locs, sps [i].il_offset);
7853                         }
7854                         g_free (sps);
7855                 } else if (!method->wrapper_type && !method->dynamic && mono_debug_image_has_debug_info (method->klass->image)) {
7856                         /* Methods without line number info like auto-generated property accessors */
7857                         seq_point_locs = mono_bitset_mem_new (mono_mempool_alloc0 (cfg->mempool, mono_bitset_alloc_size (header->code_size, 0)), header->code_size, 0);
7858                         seq_point_set_locs = mono_bitset_mem_new (mono_mempool_alloc0 (cfg->mempool, mono_bitset_alloc_size (header->code_size, 0)), header->code_size, 0);
7859                         sym_seq_points = TRUE;
7860                 }
7861         }
7862
7863         /* 
7864          * Methods without init_locals set could cause asserts in various passes
7865          * (#497220). To work around this, we emit dummy initialization opcodes
7866          * (OP_DUMMY_ICONST etc.) which generate no code. These are only supported
7867          * on some platforms.
7868          */
7869         if ((cfg->opt & MONO_OPT_UNSAFE) && cfg->backend->have_dummy_init)
7870                 init_locals = header->init_locals;
7871         else
7872                 init_locals = TRUE;
7873
7874         method_definition = method;
7875         while (method_definition->is_inflated) {
7876                 MonoMethodInflated *imethod = (MonoMethodInflated *) method_definition;
7877                 method_definition = imethod->declaring;
7878         }
7879
7880         /* SkipVerification is not allowed if core-clr is enabled */
7881         if (!dont_verify && mini_assembly_can_skip_verification (cfg->domain, method)) {
7882                 dont_verify = TRUE;
7883                 dont_verify_stloc = TRUE;
7884         }
7885
7886         if (sig->is_inflated)
7887                 generic_context = mono_method_get_context (method);
7888         else if (generic_container)
7889                 generic_context = &generic_container->context;
7890         cfg->generic_context = generic_context;
7891
7892         if (!cfg->gshared)
7893                 g_assert (!sig->has_type_parameters);
7894
7895         if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
7896                 g_assert (method->is_inflated);
7897                 g_assert (mono_method_get_context (method)->method_inst);
7898         }
7899         if (method->is_inflated && mono_method_get_context (method)->method_inst)
7900                 g_assert (sig->generic_param_count);
7901
7902         if (cfg->method == method) {
7903                 cfg->real_offset = 0;
7904         } else {
7905                 cfg->real_offset = inline_offset;
7906         }
7907
7908         cfg->cil_offset_to_bb = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoBasicBlock*) * header->code_size);
7909         cfg->cil_offset_to_bb_len = header->code_size;
7910
7911         cfg->current_method = method;
7912
7913         if (cfg->verbose_level > 2)
7914                 printf ("method to IR %s\n", mono_method_full_name (method, TRUE));
7915
7916         param_types = mono_mempool_alloc (cfg->mempool, sizeof (MonoType*) * num_args);
7917         if (sig->hasthis)
7918                 param_types [0] = method->klass->valuetype?&method->klass->this_arg:&method->klass->byval_arg;
7919         for (n = 0; n < sig->param_count; ++n)
7920                 param_types [n + sig->hasthis] = sig->params [n];
7921         cfg->arg_types = param_types;
7922
7923         cfg->dont_inline = g_list_prepend (cfg->dont_inline, method);
7924         if (cfg->method == method) {
7925
7926                 if (cfg->prof_options & MONO_PROFILE_INS_COVERAGE)
7927                         cfg->coverage_info = mono_profiler_coverage_alloc (cfg->method, header->code_size);
7928
7929                 /* ENTRY BLOCK */
7930                 NEW_BBLOCK (cfg, start_bblock);
7931                 cfg->bb_entry = start_bblock;
7932                 start_bblock->cil_code = NULL;
7933                 start_bblock->cil_length = 0;
7934
7935                 /* EXIT BLOCK */
7936                 NEW_BBLOCK (cfg, end_bblock);
7937                 cfg->bb_exit = end_bblock;
7938                 end_bblock->cil_code = NULL;
7939                 end_bblock->cil_length = 0;
7940                 end_bblock->flags |= BB_INDIRECT_JUMP_TARGET;
7941                 g_assert (cfg->num_bblocks == 2);
7942
7943                 arg_array = cfg->args;
7944
7945                 if (header->num_clauses) {
7946                         cfg->spvars = g_hash_table_new (NULL, NULL);
7947                         cfg->exvars = g_hash_table_new (NULL, NULL);
7948                 }
7949                 /* handle exception clauses */
7950                 for (i = 0; i < header->num_clauses; ++i) {
7951                         MonoBasicBlock *try_bb;
7952                         MonoExceptionClause *clause = &header->clauses [i];
7953                         GET_BBLOCK (cfg, try_bb, ip + clause->try_offset);
7954
7955                         try_bb->real_offset = clause->try_offset;
7956                         try_bb->try_start = TRUE;
7957                         try_bb->region = ((i + 1) << 8) | clause->flags;
7958                         GET_BBLOCK (cfg, tblock, ip + clause->handler_offset);
7959                         tblock->real_offset = clause->handler_offset;
7960                         tblock->flags |= BB_EXCEPTION_HANDLER;
7961
7962                         /*
7963                          * Linking the try block with the EH block hinders inlining as we won't be able to 
7964                          * merge the bblocks from inlining and produce an artificial hole for no good reason.
7965                          */
7966                         if (COMPILE_LLVM (cfg))
7967                                 link_bblock (cfg, try_bb, tblock);
7968
7969                         if (*(ip + clause->handler_offset) == CEE_POP)
7970                                 tblock->flags |= BB_EXCEPTION_DEAD_OBJ;
7971
7972                         if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY ||
7973                             clause->flags == MONO_EXCEPTION_CLAUSE_FILTER ||
7974                             clause->flags == MONO_EXCEPTION_CLAUSE_FAULT) {
7975                                 MONO_INST_NEW (cfg, ins, OP_START_HANDLER);
7976                                 MONO_ADD_INS (tblock, ins);
7977
7978                                 if (seq_points && clause->flags != MONO_EXCEPTION_CLAUSE_FINALLY && clause->flags != MONO_EXCEPTION_CLAUSE_FILTER) {
7979                                         /* finally clauses already have a seq point */
7980                                         /* seq points for filter clauses are emitted below */
7981                                         NEW_SEQ_POINT (cfg, ins, clause->handler_offset, TRUE);
7982                                         MONO_ADD_INS (tblock, ins);
7983                                 }
7984
7985                                 /* todo: is a fault block unsafe to optimize? */
7986                                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FAULT)
7987                                         tblock->flags |= BB_EXCEPTION_UNSAFE;
7988                         }
7989
7990                         /*printf ("clause try IL_%04x to IL_%04x handler %d at IL_%04x to IL_%04x\n", clause->try_offset, clause->try_offset + clause->try_len, clause->flags, clause->handler_offset, clause->handler_offset + clause->handler_len);
7991                           while (p < end) {
7992                           printf ("%s", mono_disasm_code_one (NULL, method, p, &p));
7993                           }*/
7994                         /* catch and filter blocks get the exception object on the stack */
7995                         if (clause->flags == MONO_EXCEPTION_CLAUSE_NONE ||
7996                             clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
7997
7998                                 /* mostly like handle_stack_args (), but just sets the input args */
7999                                 /* printf ("handling clause at IL_%04x\n", clause->handler_offset); */
8000                                 tblock->in_scount = 1;
8001                                 tblock->in_stack = mono_mempool_alloc (cfg->mempool, sizeof (MonoInst*));
8002                                 tblock->in_stack [0] = mono_create_exvar_for_offset (cfg, clause->handler_offset);
8003
8004                                 cfg->cbb = tblock;
8005
8006 #ifdef MONO_CONTEXT_SET_LLVM_EXC_REG
8007                                 /* The EH code passes in the exception in a register to both JITted and LLVM compiled code */
8008                                 if (!cfg->compile_llvm) {
8009                                         MONO_INST_NEW (cfg, ins, OP_GET_EX_OBJ);
8010                                         ins->dreg = tblock->in_stack [0]->dreg;
8011                                         MONO_ADD_INS (tblock, ins);
8012                                 }
8013 #else
8014                                 MonoInst *dummy_use;
8015
8016                                 /* 
8017                                  * Add a dummy use for the exvar so its liveness info will be
8018                                  * correct.
8019                                  */
8020                                 EMIT_NEW_DUMMY_USE (cfg, dummy_use, tblock->in_stack [0]);
8021 #endif
8022
8023                                 if (seq_points && clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
8024                                         NEW_SEQ_POINT (cfg, ins, clause->handler_offset, TRUE);
8025                                         MONO_ADD_INS (tblock, ins);
8026                                 }
8027                                 
8028                                 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
8029                                         GET_BBLOCK (cfg, tblock, ip + clause->data.filter_offset);
8030                                         tblock->flags |= BB_EXCEPTION_HANDLER;
8031                                         tblock->real_offset = clause->data.filter_offset;
8032                                         tblock->in_scount = 1;
8033                                         tblock->in_stack = mono_mempool_alloc (cfg->mempool, sizeof (MonoInst*));
8034                                         /* The filter block shares the exvar with the handler block */
8035                                         tblock->in_stack [0] = mono_create_exvar_for_offset (cfg, clause->handler_offset);
8036                                         MONO_INST_NEW (cfg, ins, OP_START_HANDLER);
8037                                         MONO_ADD_INS (tblock, ins);
8038                                 }
8039                         }
8040
8041                         if (clause->flags != MONO_EXCEPTION_CLAUSE_FILTER &&
8042                                         clause->data.catch_class &&
8043                                         cfg->gshared &&
8044                                         mono_class_check_context_used (clause->data.catch_class)) {
8045                                 /*
8046                                  * In shared generic code with catch
8047                                  * clauses containing type variables
8048                                  * the exception handling code has to
8049                                  * be able to get to the rgctx.
8050                                  * Therefore we have to make sure that
8051                                  * the vtable/mrgctx argument (for
8052                                  * static or generic methods) or the
8053                                  * "this" argument (for non-static
8054                                  * methods) are live.
8055                                  */
8056                                 if ((method->flags & METHOD_ATTRIBUTE_STATIC) ||
8057                                                 mini_method_get_context (method)->method_inst ||
8058                                                 method->klass->valuetype) {
8059                                         mono_get_vtable_var (cfg);
8060                                 } else {
8061                                         MonoInst *dummy_use;
8062
8063                                         EMIT_NEW_DUMMY_USE (cfg, dummy_use, arg_array [0]);
8064                                 }
8065                         }
8066                 }
8067         } else {
8068                 arg_array = (MonoInst **) alloca (sizeof (MonoInst *) * num_args);
8069                 cfg->cbb = start_bblock;
8070                 cfg->args = arg_array;
8071                 mono_save_args (cfg, sig, inline_args);
8072         }
8073
8074         /* FIRST CODE BLOCK */
8075         NEW_BBLOCK (cfg, tblock);
8076         tblock->cil_code = ip;
8077         cfg->cbb = tblock;
8078         cfg->ip = ip;
8079
8080         ADD_BBLOCK (cfg, tblock);
8081
8082         if (cfg->method == method) {
8083                 breakpoint_id = mono_debugger_method_has_breakpoint (method);
8084                 if (breakpoint_id) {
8085                         MONO_INST_NEW (cfg, ins, OP_BREAK);
8086                         MONO_ADD_INS (cfg->cbb, ins);
8087                 }
8088         }
8089
8090         /* we use a separate basic block for the initialization code */
8091         NEW_BBLOCK (cfg, init_localsbb);
8092         cfg->bb_init = init_localsbb;
8093         init_localsbb->real_offset = cfg->real_offset;
8094         start_bblock->next_bb = init_localsbb;
8095         init_localsbb->next_bb = cfg->cbb;
8096         link_bblock (cfg, start_bblock, init_localsbb);
8097         link_bblock (cfg, init_localsbb, cfg->cbb);
8098                 
8099         cfg->cbb = init_localsbb;
8100
8101         if (cfg->gsharedvt && cfg->method == method) {
8102                 MonoGSharedVtMethodInfo *info;
8103                 MonoInst *var, *locals_var;
8104                 int dreg;
8105
8106                 info = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoGSharedVtMethodInfo));
8107                 info->method = cfg->method;
8108                 info->count_entries = 16;
8109                 info->entries = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoRuntimeGenericContextInfoTemplate) * info->count_entries);
8110                 cfg->gsharedvt_info = info;
8111
8112                 var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
8113                 /* prevent it from being register allocated */
8114                 //var->flags |= MONO_INST_VOLATILE;
8115                 cfg->gsharedvt_info_var = var;
8116
8117                 ins = emit_get_rgctx_gsharedvt_method (cfg, mini_method_check_context_used (cfg, method), method, info);
8118                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, var->dreg, ins->dreg);
8119
8120                 /* Allocate locals */
8121                 locals_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
8122                 /* prevent it from being register allocated */
8123                 //locals_var->flags |= MONO_INST_VOLATILE;
8124                 cfg->gsharedvt_locals_var = locals_var;
8125
8126                 dreg = alloc_ireg (cfg);
8127                 MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, dreg, var->dreg, MONO_STRUCT_OFFSET (MonoGSharedVtMethodRuntimeInfo, locals_size));
8128
8129                 MONO_INST_NEW (cfg, ins, OP_LOCALLOC);
8130                 ins->dreg = locals_var->dreg;
8131                 ins->sreg1 = dreg;
8132                 MONO_ADD_INS (cfg->cbb, ins);
8133                 cfg->gsharedvt_locals_var_ins = ins;
8134                 
8135                 cfg->flags |= MONO_CFG_HAS_ALLOCA;
8136                 /*
8137                 if (init_locals)
8138                         ins->flags |= MONO_INST_INIT;
8139                 */
8140         }
8141
8142         if (mono_security_core_clr_enabled ()) {
8143                 /* check if this is native code, e.g. an icall or a p/invoke */
8144                 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
8145                         MonoMethod *wrapped = mono_marshal_method_from_wrapper (method);
8146                         if (wrapped) {
8147                                 gboolean pinvk = (wrapped->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL);
8148                                 gboolean icall = (wrapped->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL);
8149
8150                                 /* if this ia a native call then it can only be JITted from platform code */
8151                                 if ((icall || pinvk) && method->klass && method->klass->image) {
8152                                         if (!mono_security_core_clr_is_platform_image (method->klass->image)) {
8153                                                 MonoException *ex = icall ? mono_get_exception_security () : 
8154                                                         mono_get_exception_method_access ();
8155                                                 emit_throw_exception (cfg, ex);
8156                                         }
8157                                 }
8158                         }
8159                 }
8160         }
8161
8162         CHECK_CFG_EXCEPTION;
8163
8164         if (header->code_size == 0)
8165                 UNVERIFIED;
8166
8167         if (get_basic_blocks (cfg, header, cfg->real_offset, ip, end, &err_pos)) {
8168                 ip = err_pos;
8169                 UNVERIFIED;
8170         }
8171
8172         if (cfg->method == method)
8173                 mono_debug_init_method (cfg, cfg->cbb, breakpoint_id);
8174
8175         for (n = 0; n < header->num_locals; ++n) {
8176                 if (header->locals [n]->type == MONO_TYPE_VOID && !header->locals [n]->byref)
8177                         UNVERIFIED;
8178         }
8179         class_inits = NULL;
8180
8181         /* We force the vtable variable here for all shared methods
8182            for the possibility that they might show up in a stack
8183            trace where their exact instantiation is needed. */
8184         if (cfg->gshared && method == cfg->method) {
8185                 if ((method->flags & METHOD_ATTRIBUTE_STATIC) ||
8186                                 mini_method_get_context (method)->method_inst ||
8187                                 method->klass->valuetype) {
8188                         mono_get_vtable_var (cfg);
8189                 } else {
8190                         /* FIXME: Is there a better way to do this?
8191                            We need the variable live for the duration
8192                            of the whole method. */
8193                         cfg->args [0]->flags |= MONO_INST_VOLATILE;
8194                 }
8195         }
8196
8197         /* add a check for this != NULL to inlined methods */
8198         if (is_virtual_call) {
8199                 MonoInst *arg_ins;
8200
8201                 NEW_ARGLOAD (cfg, arg_ins, 0);
8202                 MONO_ADD_INS (cfg->cbb, arg_ins);
8203                 MONO_EMIT_NEW_CHECK_THIS (cfg, arg_ins->dreg);
8204         }
8205
8206         skip_dead_blocks = !dont_verify;
8207         if (skip_dead_blocks) {
8208                 original_bb = bb = mono_basic_block_split (method, &cfg->error);
8209                 CHECK_CFG_ERROR;
8210                 g_assert (bb);
8211         }
8212
8213         /* we use a spare stack slot in SWITCH and NEWOBJ and others */
8214         stack_start = sp = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst*) * (header->max_stack + 1));
8215
8216         ins_flag = 0;
8217         start_new_bblock = 0;
8218         while (ip < end) {
8219                 if (cfg->method == method)
8220                         cfg->real_offset = ip - header->code;
8221                 else
8222                         cfg->real_offset = inline_offset;
8223                 cfg->ip = ip;
8224
8225                 context_used = 0;
8226
8227                 if (start_new_bblock) {
8228                         cfg->cbb->cil_length = ip - cfg->cbb->cil_code;
8229                         if (start_new_bblock == 2) {
8230                                 g_assert (ip == tblock->cil_code);
8231                         } else {
8232                                 GET_BBLOCK (cfg, tblock, ip);
8233                         }
8234                         cfg->cbb->next_bb = tblock;
8235                         cfg->cbb = tblock;
8236                         start_new_bblock = 0;
8237                         for (i = 0; i < cfg->cbb->in_scount; ++i) {
8238                                 if (cfg->verbose_level > 3)
8239                                         printf ("loading %d from temp %d\n", i, (int)cfg->cbb->in_stack [i]->inst_c0);
8240                                 EMIT_NEW_TEMPLOAD (cfg, ins, cfg->cbb->in_stack [i]->inst_c0);
8241                                 *sp++ = ins;
8242                         }
8243                         if (class_inits)
8244                                 g_slist_free (class_inits);
8245                         class_inits = NULL;
8246                 } else {
8247                         if ((tblock = cfg->cil_offset_to_bb [ip - cfg->cil_start]) && (tblock != cfg->cbb)) {
8248                                 link_bblock (cfg, cfg->cbb, tblock);
8249                                 if (sp != stack_start) {
8250                                         handle_stack_args (cfg, stack_start, sp - stack_start);
8251                                         sp = stack_start;
8252                                         CHECK_UNVERIFIABLE (cfg);
8253                                 }
8254                                 cfg->cbb->next_bb = tblock;
8255                                 cfg->cbb = tblock;
8256                                 for (i = 0; i < cfg->cbb->in_scount; ++i) {
8257                                         if (cfg->verbose_level > 3)
8258                                                 printf ("loading %d from temp %d\n", i, (int)cfg->cbb->in_stack [i]->inst_c0);
8259                                         EMIT_NEW_TEMPLOAD (cfg, ins, cfg->cbb->in_stack [i]->inst_c0);
8260                                         *sp++ = ins;
8261                                 }
8262                                 g_slist_free (class_inits);
8263                                 class_inits = NULL;
8264                         }
8265                 }
8266
8267                 if (skip_dead_blocks) {
8268                         int ip_offset = ip - header->code;
8269
8270                         if (ip_offset == bb->end)
8271                                 bb = bb->next;
8272
8273                         if (bb->dead) {
8274                                 int op_size = mono_opcode_size (ip, end);
8275                                 g_assert (op_size > 0); /*The BB formation pass must catch all bad ops*/
8276
8277                                 if (cfg->verbose_level > 3) printf ("SKIPPING DEAD OP at %x\n", ip_offset);
8278
8279                                 if (ip_offset + op_size == bb->end) {
8280                                         MONO_INST_NEW (cfg, ins, OP_NOP);
8281                                         MONO_ADD_INS (cfg->cbb, ins);
8282                                         start_new_bblock = 1;
8283                                 }
8284
8285                                 ip += op_size;
8286                                 continue;
8287                         }
8288                 }
8289                 /*
8290                  * Sequence points are points where the debugger can place a breakpoint.
8291                  * Currently, we generate these automatically at points where the IL
8292                  * stack is empty.
8293                  */
8294                 if (seq_points && ((!sym_seq_points && (sp == stack_start)) || (sym_seq_points && mono_bitset_test_fast (seq_point_locs, ip - header->code)))) {
8295                         /*
8296                          * Make methods interruptable at the beginning, and at the targets of
8297                          * backward branches.
8298                          * Also, do this at the start of every bblock in methods with clauses too,
8299                          * to be able to handle instructions with inprecise control flow like
8300                          * throw/endfinally.
8301                          * Backward branches are handled at the end of method-to-ir ().
8302                          */
8303                         gboolean intr_loc = ip == header->code || (!cfg->cbb->last_ins && cfg->header->num_clauses);
8304                         gboolean sym_seq_point = sym_seq_points && mono_bitset_test_fast (seq_point_locs, ip - header->code);
8305
8306                         /* Avoid sequence points on empty IL like .volatile */
8307                         // FIXME: Enable this
8308                         //if (!(cfg->cbb->last_ins && cfg->cbb->last_ins->opcode == OP_SEQ_POINT)) {
8309                         NEW_SEQ_POINT (cfg, ins, ip - header->code, intr_loc);
8310                         if ((sp != stack_start) && !sym_seq_point)
8311                                 ins->flags |= MONO_INST_NONEMPTY_STACK;
8312                         MONO_ADD_INS (cfg->cbb, ins);
8313
8314                         if (sym_seq_points)
8315                                 mono_bitset_set_fast (seq_point_set_locs, ip - header->code);
8316                 }
8317
8318                 cfg->cbb->real_offset = cfg->real_offset;
8319
8320                 if ((cfg->method == method) && cfg->coverage_info) {
8321                         guint32 cil_offset = ip - header->code;
8322                         cfg->coverage_info->data [cil_offset].cil_code = ip;
8323
8324                         /* TODO: Use an increment here */
8325 #if defined(TARGET_X86)
8326                         MONO_INST_NEW (cfg, ins, OP_STORE_MEM_IMM);
8327                         ins->inst_p0 = &(cfg->coverage_info->data [cil_offset].count);
8328                         ins->inst_imm = 1;
8329                         MONO_ADD_INS (cfg->cbb, ins);
8330 #else
8331                         EMIT_NEW_PCONST (cfg, ins, &(cfg->coverage_info->data [cil_offset].count));
8332                         MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STORE_MEMBASE_IMM, ins->dreg, 0, 1);
8333 #endif
8334                 }
8335
8336                 if (cfg->verbose_level > 3)
8337                         printf ("converting (in B%d: stack: %d) %s", cfg->cbb->block_num, (int)(sp - stack_start), mono_disasm_code_one (NULL, method, ip, NULL));
8338
8339                 switch (*ip) {
8340                 case CEE_NOP:
8341                         if (seq_points && !sym_seq_points && sp != stack_start) {
8342                                 /*
8343                                  * The C# compiler uses these nops to notify the JIT that it should
8344                                  * insert seq points.
8345                                  */
8346                                 NEW_SEQ_POINT (cfg, ins, ip - header->code, FALSE);
8347                                 MONO_ADD_INS (cfg->cbb, ins);
8348                         }
8349                         if (cfg->keep_cil_nops)
8350                                 MONO_INST_NEW (cfg, ins, OP_HARD_NOP);
8351                         else
8352                                 MONO_INST_NEW (cfg, ins, OP_NOP);
8353                         ip++;
8354                         MONO_ADD_INS (cfg->cbb, ins);
8355                         break;
8356                 case CEE_BREAK:
8357                         if (should_insert_brekpoint (cfg->method)) {
8358                                 ins = mono_emit_jit_icall (cfg, mono_debugger_agent_user_break, NULL);
8359                         } else {
8360                                 MONO_INST_NEW (cfg, ins, OP_NOP);
8361                         }
8362                         ip++;
8363                         MONO_ADD_INS (cfg->cbb, ins);
8364                         break;
8365                 case CEE_LDARG_0:
8366                 case CEE_LDARG_1:
8367                 case CEE_LDARG_2:
8368                 case CEE_LDARG_3:
8369                         CHECK_STACK_OVF (1);
8370                         n = (*ip)-CEE_LDARG_0;
8371                         CHECK_ARG (n);
8372                         EMIT_NEW_ARGLOAD (cfg, ins, n);
8373                         ip++;
8374                         *sp++ = ins;
8375                         break;
8376                 case CEE_LDLOC_0:
8377                 case CEE_LDLOC_1:
8378                 case CEE_LDLOC_2:
8379                 case CEE_LDLOC_3:
8380                         CHECK_STACK_OVF (1);
8381                         n = (*ip)-CEE_LDLOC_0;
8382                         CHECK_LOCAL (n);
8383                         EMIT_NEW_LOCLOAD (cfg, ins, n);
8384                         ip++;
8385                         *sp++ = ins;
8386                         break;
8387                 case CEE_STLOC_0:
8388                 case CEE_STLOC_1:
8389                 case CEE_STLOC_2:
8390                 case CEE_STLOC_3: {
8391                         CHECK_STACK (1);
8392                         n = (*ip)-CEE_STLOC_0;
8393                         CHECK_LOCAL (n);
8394                         --sp;
8395                         if (!dont_verify_stloc && target_type_is_incompatible (cfg, header->locals [n], *sp))
8396                                 UNVERIFIED;
8397                         emit_stloc_ir (cfg, sp, header, n);
8398                         ++ip;
8399                         inline_costs += 1;
8400                         break;
8401                         }
8402                 case CEE_LDARG_S:
8403                         CHECK_OPSIZE (2);
8404                         CHECK_STACK_OVF (1);
8405                         n = ip [1];
8406                         CHECK_ARG (n);
8407                         EMIT_NEW_ARGLOAD (cfg, ins, n);
8408                         *sp++ = ins;
8409                         ip += 2;
8410                         break;
8411                 case CEE_LDARGA_S:
8412                         CHECK_OPSIZE (2);
8413                         CHECK_STACK_OVF (1);
8414                         n = ip [1];
8415                         CHECK_ARG (n);
8416                         NEW_ARGLOADA (cfg, ins, n);
8417                         MONO_ADD_INS (cfg->cbb, ins);
8418                         *sp++ = ins;
8419                         ip += 2;
8420                         break;
8421                 case CEE_STARG_S:
8422                         CHECK_OPSIZE (2);
8423                         CHECK_STACK (1);
8424                         --sp;
8425                         n = ip [1];
8426                         CHECK_ARG (n);
8427                         if (!dont_verify_stloc && target_type_is_incompatible (cfg, param_types [ip [1]], *sp))
8428                                 UNVERIFIED;
8429                         EMIT_NEW_ARGSTORE (cfg, ins, n, *sp);
8430                         ip += 2;
8431                         break;
8432                 case CEE_LDLOC_S:
8433                         CHECK_OPSIZE (2);
8434                         CHECK_STACK_OVF (1);
8435                         n = ip [1];
8436                         CHECK_LOCAL (n);
8437                         EMIT_NEW_LOCLOAD (cfg, ins, n);
8438                         *sp++ = ins;
8439                         ip += 2;
8440                         break;
8441                 case CEE_LDLOCA_S: {
8442                         unsigned char *tmp_ip;
8443                         CHECK_OPSIZE (2);
8444                         CHECK_STACK_OVF (1);
8445                         CHECK_LOCAL (ip [1]);
8446
8447                         if ((tmp_ip = emit_optimized_ldloca_ir (cfg, ip, end, 1))) {
8448                                 ip = tmp_ip;
8449                                 inline_costs += 1;
8450                                 break;
8451                         }
8452
8453                         EMIT_NEW_LOCLOADA (cfg, ins, ip [1]);
8454                         *sp++ = ins;
8455                         ip += 2;
8456                         break;
8457                 }
8458                 case CEE_STLOC_S:
8459                         CHECK_OPSIZE (2);
8460                         CHECK_STACK (1);
8461                         --sp;
8462                         CHECK_LOCAL (ip [1]);
8463                         if (!dont_verify_stloc && target_type_is_incompatible (cfg, header->locals [ip [1]], *sp))
8464                                 UNVERIFIED;
8465                         emit_stloc_ir (cfg, sp, header, ip [1]);
8466                         ip += 2;
8467                         inline_costs += 1;
8468                         break;
8469                 case CEE_LDNULL:
8470                         CHECK_STACK_OVF (1);
8471                         EMIT_NEW_PCONST (cfg, ins, NULL);
8472                         ins->type = STACK_OBJ;
8473                         ++ip;
8474                         *sp++ = ins;
8475                         break;
8476                 case CEE_LDC_I4_M1:
8477                         CHECK_STACK_OVF (1);
8478                         EMIT_NEW_ICONST (cfg, ins, -1);
8479                         ++ip;
8480                         *sp++ = ins;
8481                         break;
8482                 case CEE_LDC_I4_0:
8483                 case CEE_LDC_I4_1:
8484                 case CEE_LDC_I4_2:
8485                 case CEE_LDC_I4_3:
8486                 case CEE_LDC_I4_4:
8487                 case CEE_LDC_I4_5:
8488                 case CEE_LDC_I4_6:
8489                 case CEE_LDC_I4_7:
8490                 case CEE_LDC_I4_8:
8491                         CHECK_STACK_OVF (1);
8492                         EMIT_NEW_ICONST (cfg, ins, (*ip) - CEE_LDC_I4_0);
8493                         ++ip;
8494                         *sp++ = ins;
8495                         break;
8496                 case CEE_LDC_I4_S:
8497                         CHECK_OPSIZE (2);
8498                         CHECK_STACK_OVF (1);
8499                         ++ip;
8500                         EMIT_NEW_ICONST (cfg, ins, *((signed char*)ip));
8501                         ++ip;
8502                         *sp++ = ins;
8503                         break;
8504                 case CEE_LDC_I4:
8505                         CHECK_OPSIZE (5);
8506                         CHECK_STACK_OVF (1);
8507                         EMIT_NEW_ICONST (cfg, ins, (gint32)read32 (ip + 1));
8508                         ip += 5;
8509                         *sp++ = ins;
8510                         break;
8511                 case CEE_LDC_I8:
8512                         CHECK_OPSIZE (9);
8513                         CHECK_STACK_OVF (1);
8514                         MONO_INST_NEW (cfg, ins, OP_I8CONST);
8515                         ins->type = STACK_I8;
8516                         ins->dreg = alloc_dreg (cfg, STACK_I8);
8517                         ++ip;
8518                         ins->inst_l = (gint64)read64 (ip);
8519                         MONO_ADD_INS (cfg->cbb, ins);
8520                         ip += 8;
8521                         *sp++ = ins;
8522                         break;
8523                 case CEE_LDC_R4: {
8524                         float *f;
8525                         gboolean use_aotconst = FALSE;
8526
8527 #ifdef TARGET_POWERPC
8528                         /* FIXME: Clean this up */
8529                         if (cfg->compile_aot)
8530                                 use_aotconst = TRUE;
8531 #endif
8532
8533                         /* FIXME: we should really allocate this only late in the compilation process */
8534                         f = mono_domain_alloc (cfg->domain, sizeof (float));
8535                         CHECK_OPSIZE (5);
8536                         CHECK_STACK_OVF (1);
8537
8538                         if (use_aotconst) {
8539                                 MonoInst *cons;
8540                                 int dreg;
8541
8542                                 EMIT_NEW_AOTCONST (cfg, cons, MONO_PATCH_INFO_R4, f);
8543
8544                                 dreg = alloc_freg (cfg);
8545                                 EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOADR4_MEMBASE, dreg, cons->dreg, 0);
8546                                 ins->type = cfg->r4_stack_type;
8547                         } else {
8548                                 MONO_INST_NEW (cfg, ins, OP_R4CONST);
8549                                 ins->type = cfg->r4_stack_type;
8550                                 ins->dreg = alloc_dreg (cfg, STACK_R8);
8551                                 ins->inst_p0 = f;
8552                                 MONO_ADD_INS (cfg->cbb, ins);
8553                         }
8554                         ++ip;
8555                         readr4 (ip, f);
8556                         ip += 4;
8557                         *sp++ = ins;                    
8558                         break;
8559                 }
8560                 case CEE_LDC_R8: {
8561                         double *d;
8562                         gboolean use_aotconst = FALSE;
8563
8564 #ifdef TARGET_POWERPC
8565                         /* FIXME: Clean this up */
8566                         if (cfg->compile_aot)
8567                                 use_aotconst = TRUE;
8568 #endif
8569
8570                         /* FIXME: we should really allocate this only late in the compilation process */
8571                         d = mono_domain_alloc (cfg->domain, sizeof (double));
8572                         CHECK_OPSIZE (9);
8573                         CHECK_STACK_OVF (1);
8574
8575                         if (use_aotconst) {
8576                                 MonoInst *cons;
8577                                 int dreg;
8578
8579                                 EMIT_NEW_AOTCONST (cfg, cons, MONO_PATCH_INFO_R8, d);
8580
8581                                 dreg = alloc_freg (cfg);
8582                                 EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOADR8_MEMBASE, dreg, cons->dreg, 0);
8583                                 ins->type = STACK_R8;
8584                         } else {
8585                                 MONO_INST_NEW (cfg, ins, OP_R8CONST);
8586                                 ins->type = STACK_R8;
8587                                 ins->dreg = alloc_dreg (cfg, STACK_R8);
8588                                 ins->inst_p0 = d;
8589                                 MONO_ADD_INS (cfg->cbb, ins);
8590                         }
8591                         ++ip;
8592                         readr8 (ip, d);
8593                         ip += 8;
8594                         *sp++ = ins;
8595                         break;
8596                 }
8597                 case CEE_DUP: {
8598                         MonoInst *temp, *store;
8599                         CHECK_STACK (1);
8600                         CHECK_STACK_OVF (1);
8601                         sp--;
8602                         ins = *sp;
8603
8604                         temp = mono_compile_create_var (cfg, type_from_stack_type (ins), OP_LOCAL);
8605                         EMIT_NEW_TEMPSTORE (cfg, store, temp->inst_c0, ins);
8606
8607                         EMIT_NEW_TEMPLOAD (cfg, ins, temp->inst_c0);
8608                         *sp++ = ins;
8609
8610                         EMIT_NEW_TEMPLOAD (cfg, ins, temp->inst_c0);
8611                         *sp++ = ins;
8612
8613                         ++ip;
8614                         inline_costs += 2;
8615                         break;
8616                 }
8617                 case CEE_POP:
8618                         CHECK_STACK (1);
8619                         ip++;
8620                         --sp;
8621
8622 #ifdef TARGET_X86
8623                         if (sp [0]->type == STACK_R8)
8624                                 /* we need to pop the value from the x86 FP stack */
8625                                 MONO_EMIT_NEW_UNALU (cfg, OP_X86_FPOP, -1, sp [0]->dreg);
8626 #endif
8627                         break;
8628                 case CEE_JMP: {
8629                         MonoCallInst *call;
8630                         MonoMethodSignature *fsig;
8631                         int i, n;
8632
8633                         INLINE_FAILURE ("jmp");
8634                         GSHAREDVT_FAILURE (*ip);
8635
8636                         CHECK_OPSIZE (5);
8637                         if (stack_start != sp)
8638                                 UNVERIFIED;
8639                         token = read32 (ip + 1);
8640                         /* FIXME: check the signature matches */
8641                         cmethod = mini_get_method (cfg, method, token, NULL, generic_context);
8642
8643                         if (!cmethod || mono_loader_get_last_error ())
8644                                 LOAD_ERROR;
8645  
8646                         if (cfg->gshared && mono_method_check_context_used (cmethod))
8647                                 GENERIC_SHARING_FAILURE (CEE_JMP);
8648
8649                         emit_instrumentation_call (cfg, mono_profiler_method_leave);
8650
8651                         fsig = mono_method_signature (cmethod);
8652                         n = fsig->param_count + fsig->hasthis;
8653                         if (cfg->llvm_only) {
8654                                 MonoInst **args;
8655
8656                                 args = mono_mempool_alloc (cfg->mempool, sizeof (MonoInst*) * n);
8657                                 for (i = 0; i < n; ++i)
8658                                         EMIT_NEW_ARGLOAD (cfg, args [i], i);
8659                                 ins = mono_emit_method_call_full (cfg, cmethod, fsig, TRUE, args, NULL, NULL, NULL);
8660                                 /*
8661                                  * The code in mono-basic-block.c treats the rest of the code as dead, but we
8662                                  * have to emit a normal return since llvm expects it.
8663                                  */
8664                                 if (cfg->ret)
8665                                         emit_setret (cfg, ins);
8666                                 MONO_INST_NEW (cfg, ins, OP_BR);
8667                                 ins->inst_target_bb = end_bblock;
8668                                 MONO_ADD_INS (cfg->cbb, ins);
8669                                 link_bblock (cfg, cfg->cbb, end_bblock);
8670                                 ip += 5;
8671                                 break;
8672                         } else if (cfg->backend->have_op_tail_call) {
8673                                 /* Handle tail calls similarly to calls */
8674                                 DISABLE_AOT (cfg);
8675
8676                                 MONO_INST_NEW_CALL (cfg, call, OP_TAILCALL);
8677                                 call->method = cmethod;
8678                                 call->tail_call = TRUE;
8679                                 call->signature = mono_method_signature (cmethod);
8680                                 call->args = mono_mempool_alloc (cfg->mempool, sizeof (MonoInst*) * n);
8681                                 call->inst.inst_p0 = cmethod;
8682                                 for (i = 0; i < n; ++i)
8683                                         EMIT_NEW_ARGLOAD (cfg, call->args [i], i);
8684
8685                                 mono_arch_emit_call (cfg, call);
8686                                 cfg->param_area = MAX(cfg->param_area, call->stack_usage);
8687                                 MONO_ADD_INS (cfg->cbb, (MonoInst*)call);
8688                         } else {
8689                                 for (i = 0; i < num_args; ++i)
8690                                         /* Prevent arguments from being optimized away */
8691                                         arg_array [i]->flags |= MONO_INST_VOLATILE;
8692
8693                                 MONO_INST_NEW_CALL (cfg, call, OP_JMP);
8694                                 ins = (MonoInst*)call;
8695                                 ins->inst_p0 = cmethod;
8696                                 MONO_ADD_INS (cfg->cbb, ins);
8697                         }
8698
8699                         ip += 5;
8700                         start_new_bblock = 1;
8701                         break;
8702                 }
8703                 case CEE_CALLI: {
8704                         MonoInst *addr;
8705                         MonoMethodSignature *fsig;
8706
8707                         CHECK_OPSIZE (5);
8708                         token = read32 (ip + 1);
8709
8710                         ins = NULL;
8711
8712                         //GSHAREDVT_FAILURE (*ip);
8713                         cmethod = NULL;
8714                         CHECK_STACK (1);
8715                         --sp;
8716                         addr = *sp;
8717                         fsig = mini_get_signature (method, token, generic_context);
8718
8719                         if (method->dynamic && fsig->pinvoke) {
8720                                 MonoInst *args [3];
8721
8722                                 /*
8723                                  * This is a call through a function pointer using a pinvoke
8724                                  * signature. Have to create a wrapper and call that instead.
8725                                  * FIXME: This is very slow, need to create a wrapper at JIT time
8726                                  * instead based on the signature.
8727                                  */
8728                                 EMIT_NEW_IMAGECONST (cfg, args [0], method->klass->image);
8729                                 EMIT_NEW_PCONST (cfg, args [1], fsig);
8730                                 args [2] = addr;
8731                                 addr = mono_emit_jit_icall (cfg, mono_get_native_calli_wrapper, args);
8732                         }
8733
8734                         n = fsig->param_count + fsig->hasthis;
8735
8736                         CHECK_STACK (n);
8737
8738                         //g_assert (!virtual || fsig->hasthis);
8739
8740                         sp -= n;
8741
8742                         inline_costs += 10 * num_calls++;
8743
8744                         /*
8745                          * Making generic calls out of gsharedvt methods.
8746                          * This needs to be used for all generic calls, not just ones with a gsharedvt signature, to avoid
8747                          * patching gshared method addresses into a gsharedvt method.
8748                          */
8749                         if (cfg->gsharedvt && mini_is_gsharedvt_signature (fsig)) {
8750                                 /*
8751                                  * We pass the address to the gsharedvt trampoline in the rgctx reg
8752                                  */
8753                                 MonoInst *callee = addr;
8754
8755                                 if (method->wrapper_type != MONO_WRAPPER_DELEGATE_INVOKE)
8756                                         /* Not tested */
8757                                         GSHAREDVT_FAILURE (*ip);
8758
8759                                 addr = emit_get_rgctx_sig (cfg, context_used,
8760                                                                                           fsig, MONO_RGCTX_INFO_SIG_GSHAREDVT_OUT_TRAMPOLINE_CALLI);
8761                                 ins = (MonoInst*)mono_emit_calli (cfg, fsig, sp, addr, NULL, callee);
8762                                 goto calli_end;
8763                         }
8764
8765                         /* Prevent inlining of methods with indirect calls */
8766                         INLINE_FAILURE ("indirect call");
8767
8768                         if (addr->opcode == OP_PCONST || addr->opcode == OP_AOTCONST || addr->opcode == OP_GOT_ENTRY) {
8769                                 int info_type;
8770                                 gpointer info_data;
8771
8772                                 /*
8773                                  * Instead of emitting an indirect call, emit a direct call
8774                                  * with the contents of the aotconst as the patch info.
8775                                  */
8776                                 if (addr->opcode == OP_PCONST || addr->opcode == OP_AOTCONST) {
8777                                         info_type = addr->inst_c1;
8778                                         info_data = addr->inst_p0;
8779                                 } else {
8780                                         info_type = addr->inst_right->inst_c1;
8781                                         info_data = addr->inst_right->inst_left;
8782                                 }
8783
8784                                 if (info_type == MONO_PATCH_INFO_ICALL_ADDR || info_type == MONO_PATCH_INFO_JIT_ICALL_ADDR) {
8785                                         ins = (MonoInst*)mono_emit_abs_call (cfg, info_type, info_data, fsig, sp);
8786                                         NULLIFY_INS (addr);
8787                                         goto calli_end;
8788                                 }
8789                         }
8790                         ins = (MonoInst*)mono_emit_calli (cfg, fsig, sp, addr, NULL, NULL);
8791
8792                         calli_end:
8793
8794                         /* End of call, INS should contain the result of the call, if any */
8795
8796                         if (!MONO_TYPE_IS_VOID (fsig->ret)) {
8797                                 g_assert (ins);
8798                                 *sp++ = mono_emit_widen_call_res (cfg, ins, fsig);
8799                         }
8800
8801                         CHECK_CFG_EXCEPTION;
8802
8803                         ip += 5;
8804                         ins_flag = 0;
8805                         constrained_class = NULL;
8806                         break;
8807                 }
8808                 case CEE_CALL:
8809                 case CEE_CALLVIRT: {
8810                         MonoInst *addr = NULL;
8811                         MonoMethodSignature *fsig = NULL;
8812                         int array_rank = 0;
8813                         int virtual = *ip == CEE_CALLVIRT;
8814                         gboolean pass_imt_from_rgctx = FALSE;
8815                         MonoInst *imt_arg = NULL;
8816                         MonoInst *keep_this_alive = NULL;
8817                         gboolean pass_vtable = FALSE;
8818                         gboolean pass_mrgctx = FALSE;
8819                         MonoInst *vtable_arg = NULL;
8820                         gboolean check_this = FALSE;
8821                         gboolean supported_tail_call = FALSE;
8822                         gboolean tail_call = FALSE;
8823                         gboolean need_seq_point = FALSE;
8824                         guint32 call_opcode = *ip;
8825                         gboolean emit_widen = TRUE;
8826                         gboolean push_res = TRUE;
8827                         gboolean skip_ret = FALSE;
8828                         gboolean delegate_invoke = FALSE;
8829                         gboolean direct_icall = FALSE;
8830                         gboolean constrained_partial_call = FALSE;
8831                         MonoMethod *cil_method;
8832
8833                         CHECK_OPSIZE (5);
8834                         token = read32 (ip + 1);
8835
8836                         ins = NULL;
8837
8838                         cmethod = mini_get_method (cfg, method, token, NULL, generic_context);
8839                         cil_method = cmethod;
8840                                 
8841                         if (constrained_class) {
8842                                 if ((constrained_class->byval_arg.type == MONO_TYPE_VAR || constrained_class->byval_arg.type == MONO_TYPE_MVAR) && cfg->gshared) {
8843                                         if (!mini_is_gsharedvt_klass (constrained_class)) {
8844                                                 g_assert (!cmethod->klass->valuetype);
8845                                                 if (!mini_type_is_reference (&constrained_class->byval_arg))
8846                                                         constrained_partial_call = TRUE;
8847                                         }
8848                                 }
8849
8850                                 if (method->wrapper_type != MONO_WRAPPER_NONE) {
8851                                         if (cfg->verbose_level > 2)
8852                                                 printf ("DM Constrained call to %s\n", mono_type_get_full_name (constrained_class));
8853                                         if (!((constrained_class->byval_arg.type == MONO_TYPE_VAR ||
8854                                                    constrained_class->byval_arg.type == MONO_TYPE_MVAR) &&
8855                                                   cfg->gshared)) {
8856                                                 cmethod = mono_get_method_constrained_with_method (image, cil_method, constrained_class, generic_context, &cfg->error);
8857                                                 CHECK_CFG_ERROR;
8858                                         }
8859                                 } else {
8860                                         if (cfg->verbose_level > 2)
8861                                                 printf ("Constrained call to %s\n", mono_type_get_full_name (constrained_class));
8862
8863                                         if ((constrained_class->byval_arg.type == MONO_TYPE_VAR || constrained_class->byval_arg.type == MONO_TYPE_MVAR) && cfg->gshared) {
8864                                                 /* 
8865                                                  * This is needed since get_method_constrained can't find 
8866                                                  * the method in klass representing a type var.
8867                                                  * The type var is guaranteed to be a reference type in this
8868                                                  * case.
8869                                                  */
8870                                                 if (!mini_is_gsharedvt_klass (constrained_class))
8871                                                         g_assert (!cmethod->klass->valuetype);
8872                                         } else {
8873                                                 cmethod = mono_get_method_constrained_checked (image, token, constrained_class, generic_context, &cil_method, &cfg->error);
8874                                                 CHECK_CFG_ERROR;
8875                                         }
8876                                 }
8877                         }
8878                                         
8879                         if (!cmethod || mono_loader_get_last_error ())
8880                                 LOAD_ERROR;
8881                         if (!dont_verify && !cfg->skip_visibility) {
8882                                 MonoMethod *target_method = cil_method;
8883                                 if (method->is_inflated) {
8884                                         target_method = mini_get_method_allow_open (method, token, NULL, &(mono_method_get_generic_container (method_definition)->context));
8885                                 }
8886                                 if (!mono_method_can_access_method (method_definition, target_method) &&
8887                                         !mono_method_can_access_method (method, cil_method))
8888                                         METHOD_ACCESS_FAILURE (method, cil_method);
8889                         }
8890
8891                         if (mono_security_core_clr_enabled ())
8892                                 ensure_method_is_allowed_to_call_method (cfg, method, cil_method);
8893
8894                         if (!virtual && (cmethod->flags & METHOD_ATTRIBUTE_ABSTRACT))
8895                                 /* MS.NET seems to silently convert this to a callvirt */
8896                                 virtual = 1;
8897
8898                         {
8899                                 /*
8900                                  * MS.NET accepts non virtual calls to virtual final methods of transparent proxy classes and
8901                                  * converts to a callvirt.
8902                                  *
8903                                  * tests/bug-515884.il is an example of this behavior
8904                                  */
8905                                 const int test_flags = METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_FINAL | METHOD_ATTRIBUTE_STATIC;
8906                                 const int expected_flags = METHOD_ATTRIBUTE_VIRTUAL | METHOD_ATTRIBUTE_FINAL;
8907                                 if (!virtual && mono_class_is_marshalbyref (cmethod->klass) && (cmethod->flags & test_flags) == expected_flags && cfg->method->wrapper_type == MONO_WRAPPER_NONE)
8908                                         virtual = 1;
8909                         }
8910
8911                         if (!cmethod->klass->inited)
8912                                 if (!mono_class_init (cmethod->klass))
8913                                         TYPE_LOAD_ERROR (cmethod->klass);
8914
8915                         fsig = mono_method_signature (cmethod);
8916                         if (!fsig)
8917                                 LOAD_ERROR;
8918                         if (cmethod->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL &&
8919                                 mini_class_is_system_array (cmethod->klass)) {
8920                                 array_rank = cmethod->klass->rank;
8921                         } else if ((cmethod->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) && icall_is_direct_callable (cfg, cmethod)) {
8922                                 direct_icall = TRUE;
8923                         } else if (fsig->pinvoke) {
8924                                 MonoMethod *wrapper = mono_marshal_get_native_wrapper (cmethod, TRUE, cfg->compile_aot);
8925                                 fsig = mono_method_signature (wrapper);
8926                         } else if (constrained_class) {
8927                         } else {
8928                                 fsig = mono_method_get_signature_checked (cmethod, image, token, generic_context, &cfg->error);
8929                                 CHECK_CFG_ERROR;
8930                         }
8931
8932                         /* See code below */
8933                         if (cmethod->klass == mono_defaults.monitor_class && !strcmp (cmethod->name, "Enter") && mono_method_signature (cmethod)->param_count == 1) {
8934                                 MonoBasicBlock *tbb;
8935
8936                                 GET_BBLOCK (cfg, tbb, ip + 5);
8937                                 if (tbb->try_start && MONO_REGION_FLAGS(tbb->region) == MONO_EXCEPTION_CLAUSE_FINALLY) {
8938                                         /*
8939                                          * We want to extend the try block to cover the call, but we can't do it if the
8940                                          * call is made directly since its followed by an exception check.
8941                                          */
8942                                         direct_icall = FALSE;
8943                                 }
8944                         }
8945
8946                         mono_save_token_info (cfg, image, token, cil_method);
8947
8948                         if (!(seq_point_locs && mono_bitset_test_fast (seq_point_locs, ip + 5 - header->code)))
8949                                 need_seq_point = TRUE;
8950
8951                         /* Don't support calls made using type arguments for now */
8952                         /*
8953                           if (cfg->gsharedvt) {
8954                           if (mini_is_gsharedvt_signature (fsig))
8955                           GSHAREDVT_FAILURE (*ip);
8956                           }
8957                         */
8958
8959                         if (cmethod->string_ctor && method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE)
8960                                 g_assert_not_reached ();
8961
8962                         n = fsig->param_count + fsig->hasthis;
8963
8964                         if (!cfg->gshared && cmethod->klass->generic_container)
8965                                 UNVERIFIED;
8966
8967                         if (!cfg->gshared)
8968                                 g_assert (!mono_method_check_context_used (cmethod));
8969
8970                         CHECK_STACK (n);
8971
8972                         //g_assert (!virtual || fsig->hasthis);
8973
8974                         sp -= n;
8975
8976                         if (constrained_class) {
8977                                 if (mini_is_gsharedvt_klass (constrained_class)) {
8978                                         if ((cmethod->klass != mono_defaults.object_class) && constrained_class->valuetype && cmethod->klass->valuetype) {
8979                                                 /* The 'Own method' case below */
8980                                         } else if (cmethod->klass->image != mono_defaults.corlib && !(cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE) && !cmethod->klass->valuetype) {
8981                                                 /* 'The type parameter is instantiated as a reference type' case below. */
8982                                         } else {
8983                                                 ins = handle_constrained_gsharedvt_call (cfg, cmethod, fsig, sp, constrained_class, &emit_widen);
8984                                                 CHECK_CFG_EXCEPTION;
8985                                                 g_assert (ins);
8986                                                 goto call_end;
8987                                         }
8988                                 }
8989
8990                                 /*
8991                                  * We have the `constrained.' prefix opcode.
8992                                  */
8993                                 if (constrained_partial_call) {
8994                                         gboolean need_box = TRUE;
8995
8996                                         /*
8997                                          * The receiver is a valuetype, but the exact type is not known at compile time. This means the
8998                                          * called method is not known at compile time either. The called method could end up being
8999                                          * one of the methods on the parent classes (object/valuetype/enum), in which case we need
9000                                          * to box the receiver.
9001                                          * A simple solution would be to box always and make a normal virtual call, but that would
9002                                          * be bad performance wise.
9003                                          */
9004                                         if (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE && cmethod->klass->generic_class) {
9005                                                 /*
9006                                                  * The parent classes implement no generic interfaces, so the called method will be a vtype method, so no boxing neccessary.
9007                                                  */
9008                                                 need_box = FALSE;
9009                                         }
9010
9011                                         if (!(cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL) && (cmethod->klass == mono_defaults.object_class || cmethod->klass == mono_defaults.enum_class->parent || cmethod->klass == mono_defaults.enum_class)) {
9012                                                 /* The called method is not virtual, i.e. Object:GetType (), the receiver is a vtype, has to box */
9013                                                 EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &constrained_class->byval_arg, sp [0]->dreg, 0);
9014                                                 ins->klass = constrained_class;
9015                                                 sp [0] = handle_box (cfg, ins, constrained_class, mono_class_check_context_used (constrained_class));
9016                                                 CHECK_CFG_EXCEPTION;
9017                                         } else if (need_box) {
9018                                                 MonoInst *box_type;
9019                                                 MonoBasicBlock *is_ref_bb, *end_bb;
9020                                                 MonoInst *nonbox_call;
9021
9022                                                 /*
9023                                                  * Determine at runtime whenever the called method is defined on object/valuetype/enum, and emit a boxing call
9024                                                  * if needed.
9025                                                  * FIXME: It is possible to inline the called method in a lot of cases, i.e. for T_INT,
9026                                                  * the no-box case goes to a method in Int32, while the box case goes to a method in Enum.
9027                                                  */
9028                                                 addr = emit_get_rgctx_virt_method (cfg, mono_class_check_context_used (constrained_class), constrained_class, cmethod, MONO_RGCTX_INFO_VIRT_METHOD_CODE);
9029
9030                                                 NEW_BBLOCK (cfg, is_ref_bb);
9031                                                 NEW_BBLOCK (cfg, end_bb);
9032
9033                                                 box_type = emit_get_rgctx_virt_method (cfg, mono_class_check_context_used (constrained_class), constrained_class, cmethod, MONO_RGCTX_INFO_VIRT_METHOD_BOX_TYPE);
9034                                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, box_type->dreg, 1);
9035                                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, is_ref_bb);
9036
9037                                                 /* Non-ref case */
9038                                                 nonbox_call = (MonoInst*)mono_emit_calli (cfg, fsig, sp, addr, NULL, NULL);
9039
9040                                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
9041
9042                                                 /* Ref case */
9043                                                 MONO_START_BB (cfg, is_ref_bb);
9044                                                 EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &constrained_class->byval_arg, sp [0]->dreg, 0);
9045                                                 ins->klass = constrained_class;
9046                                                 sp [0] = handle_box (cfg, ins, constrained_class, mono_class_check_context_used (constrained_class));
9047                                                 ins = (MonoInst*)mono_emit_calli (cfg, fsig, sp, addr, NULL, NULL);
9048
9049                                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
9050
9051                                                 MONO_START_BB (cfg, end_bb);
9052                                                 cfg->cbb = end_bb;
9053
9054                                                 nonbox_call->dreg = ins->dreg;
9055                                                 goto call_end;
9056                                         } else {
9057                                                 g_assert (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE);
9058                                                 addr = emit_get_rgctx_virt_method (cfg, mono_class_check_context_used (constrained_class), constrained_class, cmethod, MONO_RGCTX_INFO_VIRT_METHOD_CODE);
9059                                                 ins = (MonoInst*)mono_emit_calli (cfg, fsig, sp, addr, NULL, NULL);
9060                                                 goto call_end;
9061                                         }
9062                                 } else if (constrained_class->valuetype && (cmethod->klass == mono_defaults.object_class || cmethod->klass == mono_defaults.enum_class->parent || cmethod->klass == mono_defaults.enum_class)) {
9063                                         /*
9064                                          * The type parameter is instantiated as a valuetype,
9065                                          * but that type doesn't override the method we're
9066                                          * calling, so we need to box `this'.
9067                                          */
9068                                         EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &constrained_class->byval_arg, sp [0]->dreg, 0);
9069                                         ins->klass = constrained_class;
9070                                         sp [0] = handle_box (cfg, ins, constrained_class, mono_class_check_context_used (constrained_class));
9071                                         CHECK_CFG_EXCEPTION;
9072                                 } else if (!constrained_class->valuetype) {
9073                                         int dreg = alloc_ireg_ref (cfg);
9074
9075                                         /*
9076                                          * The type parameter is instantiated as a reference
9077                                          * type.  We have a managed pointer on the stack, so
9078                                          * we need to dereference it here.
9079                                          */
9080                                         EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, dreg, sp [0]->dreg, 0);
9081                                         ins->type = STACK_OBJ;
9082                                         sp [0] = ins;
9083                                 } else {
9084                                         if (cmethod->klass->valuetype) {
9085                                                 /* Own method */
9086                                         } else {
9087                                                 /* Interface method */
9088                                                 int ioffset, slot;
9089
9090                                                 mono_class_setup_vtable (constrained_class);
9091                                                 CHECK_TYPELOAD (constrained_class);
9092                                                 ioffset = mono_class_interface_offset (constrained_class, cmethod->klass);
9093                                                 if (ioffset == -1)
9094                                                         TYPE_LOAD_ERROR (constrained_class);
9095                                                 slot = mono_method_get_vtable_slot (cmethod);
9096                                                 if (slot == -1)
9097                                                         TYPE_LOAD_ERROR (cmethod->klass);
9098                                                 cmethod = constrained_class->vtable [ioffset + slot];
9099
9100                                                 if (cmethod->klass == mono_defaults.enum_class) {
9101                                                         /* Enum implements some interfaces, so treat this as the first case */
9102                                                         EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &constrained_class->byval_arg, sp [0]->dreg, 0);
9103                                                         ins->klass = constrained_class;
9104                                                         sp [0] = handle_box (cfg, ins, constrained_class, mono_class_check_context_used (constrained_class));
9105                                                         CHECK_CFG_EXCEPTION;
9106                                                 }
9107                                         }
9108                                         virtual = 0;
9109                                 }
9110                                 constrained_class = NULL;
9111                         }
9112
9113                         if (check_call_signature (cfg, fsig, sp))
9114                                 UNVERIFIED;
9115
9116                         if ((cmethod->klass->parent == mono_defaults.multicastdelegate_class) && !strcmp (cmethod->name, "Invoke"))
9117                                 delegate_invoke = TRUE;
9118
9119                         if ((cfg->opt & MONO_OPT_INTRINS) && (ins = mini_emit_inst_for_sharable_method (cfg, cmethod, fsig, sp))) {
9120                                 if (!MONO_TYPE_IS_VOID (fsig->ret)) {
9121                                         type_to_eval_stack_type ((cfg), fsig->ret, ins);
9122                                         emit_widen = FALSE;
9123                                 }
9124
9125                                 goto call_end;
9126                         }
9127
9128                         /* 
9129                          * If the callee is a shared method, then its static cctor
9130                          * might not get called after the call was patched.
9131                          */
9132                         if (cfg->gshared && cmethod->klass != method->klass && cmethod->klass->generic_class && mono_method_is_generic_sharable (cmethod, TRUE) && mono_class_needs_cctor_run (cmethod->klass, method)) {
9133                                 emit_class_init (cfg, cmethod->klass);
9134                                 CHECK_TYPELOAD (cmethod->klass);
9135                         }
9136
9137                         check_method_sharing (cfg, cmethod, &pass_vtable, &pass_mrgctx);
9138
9139                         if (cfg->gshared) {
9140                                 MonoGenericContext *cmethod_context = mono_method_get_context (cmethod);
9141
9142                                 context_used = mini_method_check_context_used (cfg, cmethod);
9143
9144                                 if (context_used && (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
9145                                         /* Generic method interface
9146                                            calls are resolved via a
9147                                            helper function and don't
9148                                            need an imt. */
9149                                         if (!cmethod_context || !cmethod_context->method_inst)
9150                                                 pass_imt_from_rgctx = TRUE;
9151                                 }
9152
9153                                 /*
9154                                  * If a shared method calls another
9155                                  * shared method then the caller must
9156                                  * have a generic sharing context
9157                                  * because the magic trampoline
9158                                  * requires it.  FIXME: We shouldn't
9159                                  * have to force the vtable/mrgctx
9160                                  * variable here.  Instead there
9161                                  * should be a flag in the cfg to
9162                                  * request a generic sharing context.
9163                                  */
9164                                 if (context_used &&
9165                                                 ((method->flags & METHOD_ATTRIBUTE_STATIC) || method->klass->valuetype))
9166                                         mono_get_vtable_var (cfg);
9167                         }
9168
9169                         if (pass_vtable) {
9170                                 if (context_used) {
9171                                         vtable_arg = emit_get_rgctx_klass (cfg, context_used, cmethod->klass, MONO_RGCTX_INFO_VTABLE);
9172                                 } else {
9173                                         MonoVTable *vtable = mono_class_vtable (cfg->domain, cmethod->klass);
9174
9175                                         CHECK_TYPELOAD (cmethod->klass);
9176                                         EMIT_NEW_VTABLECONST (cfg, vtable_arg, vtable);
9177                                 }
9178                         }
9179
9180                         if (pass_mrgctx) {
9181                                 g_assert (!vtable_arg);
9182
9183                                 if (!cfg->compile_aot) {
9184                                         /* 
9185                                          * emit_get_rgctx_method () calls mono_class_vtable () so check 
9186                                          * for type load errors before.
9187                                          */
9188                                         mono_class_setup_vtable (cmethod->klass);
9189                                         CHECK_TYPELOAD (cmethod->klass);
9190                                 }
9191
9192                                 vtable_arg = emit_get_rgctx_method (cfg, context_used, cmethod, MONO_RGCTX_INFO_METHOD_RGCTX);
9193
9194                                 /* !marshalbyref is needed to properly handle generic methods + remoting */
9195                                 if ((!(cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
9196                                          MONO_METHOD_IS_FINAL (cmethod)) &&
9197                                         !mono_class_is_marshalbyref (cmethod->klass)) {
9198                                         if (virtual)
9199                                                 check_this = TRUE;
9200                                         virtual = 0;
9201                                 }
9202                         }
9203
9204                         if (pass_imt_from_rgctx) {
9205                                 g_assert (!pass_vtable);
9206
9207                                 imt_arg = emit_get_rgctx_method (cfg, context_used,
9208                                         cmethod, MONO_RGCTX_INFO_METHOD);
9209                         }
9210
9211                         if (check_this)
9212                                 MONO_EMIT_NEW_CHECK_THIS (cfg, sp [0]->dreg);
9213
9214                         /* Calling virtual generic methods */
9215                         if (virtual && (cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL) && 
9216                             !(MONO_METHOD_IS_FINAL (cmethod) && 
9217                               cmethod->wrapper_type != MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK) &&
9218                             fsig->generic_param_count && 
9219                                 !(cfg->gsharedvt && mini_is_gsharedvt_signature (fsig)) &&
9220                                 !cfg->llvm_only) {
9221                                 MonoInst *this_temp, *this_arg_temp, *store;
9222                                 MonoInst *iargs [4];
9223
9224                                 g_assert (fsig->is_inflated);
9225
9226                                 /* Prevent inlining of methods that contain indirect calls */
9227                                 INLINE_FAILURE ("virtual generic call");
9228
9229                                 if (cfg->gsharedvt && mini_is_gsharedvt_signature (fsig))
9230                                         GSHAREDVT_FAILURE (*ip);
9231
9232                                 if (cfg->backend->have_generalized_imt_thunk && cfg->backend->gshared_supported && cmethod->wrapper_type == MONO_WRAPPER_NONE) {
9233                                         g_assert (!imt_arg);
9234                                         if (!context_used)
9235                                                 g_assert (cmethod->is_inflated);
9236                                         imt_arg = emit_get_rgctx_method (cfg, context_used,
9237                                                                                                          cmethod, MONO_RGCTX_INFO_METHOD);
9238                                         ins = mono_emit_method_call_full (cfg, cmethod, fsig, FALSE, sp, sp [0], imt_arg, NULL);
9239                                 } else {
9240                                         this_temp = mono_compile_create_var (cfg, type_from_stack_type (sp [0]), OP_LOCAL);
9241                                         NEW_TEMPSTORE (cfg, store, this_temp->inst_c0, sp [0]);
9242                                         MONO_ADD_INS (cfg->cbb, store);
9243
9244                                         /* FIXME: This should be a managed pointer */
9245                                         this_arg_temp = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
9246
9247                                         EMIT_NEW_TEMPLOAD (cfg, iargs [0], this_temp->inst_c0);
9248                                         iargs [1] = emit_get_rgctx_method (cfg, context_used,
9249                                                                                                            cmethod, MONO_RGCTX_INFO_METHOD);
9250                                         EMIT_NEW_TEMPLOADA (cfg, iargs [2], this_arg_temp->inst_c0);
9251                                         addr = mono_emit_jit_icall (cfg,
9252                                                                                                 mono_helper_compile_generic_method, iargs);
9253
9254                                         EMIT_NEW_TEMPLOAD (cfg, sp [0], this_arg_temp->inst_c0);
9255
9256                                         ins = (MonoInst*)mono_emit_calli (cfg, fsig, sp, addr, NULL, NULL);
9257                                 }
9258
9259                                 goto call_end;
9260                         }
9261
9262                         /*
9263                          * Implement a workaround for the inherent races involved in locking:
9264                          * Monitor.Enter ()
9265                          * try {
9266                          * } finally {
9267                          *    Monitor.Exit ()
9268                          * }
9269                          * If a thread abort happens between the call to Monitor.Enter () and the start of the
9270                          * try block, the Exit () won't be executed, see:
9271                          * http://www.bluebytesoftware.com/blog/2007/01/30/MonitorEnterThreadAbortsAndOrphanedLocks.aspx
9272                          * To work around this, we extend such try blocks to include the last x bytes
9273                          * of the Monitor.Enter () call.
9274                          */
9275                         if (cmethod->klass == mono_defaults.monitor_class && !strcmp (cmethod->name, "Enter") && mono_method_signature (cmethod)->param_count == 1) {
9276                                 MonoBasicBlock *tbb;
9277
9278                                 GET_BBLOCK (cfg, tbb, ip + 5);
9279                                 /* 
9280                                  * Only extend try blocks with a finally, to avoid catching exceptions thrown
9281                                  * from Monitor.Enter like ArgumentNullException.
9282                                  */
9283                                 if (tbb->try_start && MONO_REGION_FLAGS(tbb->region) == MONO_EXCEPTION_CLAUSE_FINALLY) {
9284                                         /* Mark this bblock as needing to be extended */
9285                                         tbb->extend_try_block = TRUE;
9286                                 }
9287                         }
9288
9289                         /* Conversion to a JIT intrinsic */
9290                         if ((cfg->opt & MONO_OPT_INTRINS) && (ins = mini_emit_inst_for_method (cfg, cmethod, fsig, sp))) {
9291                                 if (!MONO_TYPE_IS_VOID (fsig->ret)) {
9292                                         type_to_eval_stack_type ((cfg), fsig->ret, ins);
9293                                         emit_widen = FALSE;
9294                                 }
9295                                 goto call_end;
9296                         }
9297
9298                         /* Inlining */
9299                         if ((cfg->opt & MONO_OPT_INLINE) &&
9300                                 (!virtual || !(cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL) || MONO_METHOD_IS_FINAL (cmethod)) &&
9301                             mono_method_check_inlining (cfg, cmethod)) {
9302                                 int costs;
9303                                 gboolean always = FALSE;
9304
9305                                 if ((cmethod->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
9306                                         (cmethod->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
9307                                         /* Prevent inlining of methods that call wrappers */
9308                                         INLINE_FAILURE ("wrapper call");
9309                                         cmethod = mono_marshal_get_native_wrapper (cmethod, TRUE, FALSE);
9310                                         always = TRUE;
9311                                 }
9312
9313                                 costs = inline_method (cfg, cmethod, fsig, sp, ip, cfg->real_offset, always);
9314                                 if (costs) {
9315                                         cfg->real_offset += 5;
9316
9317                                         if (!MONO_TYPE_IS_VOID (fsig->ret)) {
9318                                                 /* *sp is already set by inline_method */
9319                                                 sp++;
9320                                                 push_res = FALSE;
9321                                         }
9322
9323                                         inline_costs += costs;
9324
9325                                         goto call_end;
9326                                 }
9327                         }
9328
9329                         /* Tail recursion elimination */
9330                         if ((cfg->opt & MONO_OPT_TAILC) && call_opcode == CEE_CALL && cmethod == method && ip [5] == CEE_RET && !vtable_arg) {
9331                                 gboolean has_vtargs = FALSE;
9332                                 int i;
9333
9334                                 /* Prevent inlining of methods with tail calls (the call stack would be altered) */
9335                                 INLINE_FAILURE ("tail call");
9336
9337                                 /* keep it simple */
9338                                 for (i =  fsig->param_count - 1; i >= 0; i--) {
9339                                         if (MONO_TYPE_ISSTRUCT (mono_method_signature (cmethod)->params [i])) 
9340                                                 has_vtargs = TRUE;
9341                                 }
9342
9343                                 if (!has_vtargs) {
9344                                         for (i = 0; i < n; ++i)
9345                                                 EMIT_NEW_ARGSTORE (cfg, ins, i, sp [i]);
9346                                         MONO_INST_NEW (cfg, ins, OP_BR);
9347                                         MONO_ADD_INS (cfg->cbb, ins);
9348                                         tblock = start_bblock->out_bb [0];
9349                                         link_bblock (cfg, cfg->cbb, tblock);
9350                                         ins->inst_target_bb = tblock;
9351                                         start_new_bblock = 1;
9352
9353                                         /* skip the CEE_RET, too */
9354                                         if (ip_in_bb (cfg, cfg->cbb, ip + 5))
9355                                                 skip_ret = TRUE;
9356                                         push_res = FALSE;
9357                                         goto call_end;
9358                                 }
9359                         }
9360
9361                         inline_costs += 10 * num_calls++;
9362
9363                         /*
9364                          * Making generic calls out of gsharedvt methods.
9365                          * This needs to be used for all generic calls, not just ones with a gsharedvt signature, to avoid
9366                          * patching gshared method addresses into a gsharedvt method.
9367                          */
9368                         if (cfg->gsharedvt && (mini_is_gsharedvt_signature (fsig) || cmethod->is_inflated || cmethod->klass->generic_class) &&
9369                                 !(cmethod->klass->rank && cmethod->klass->byval_arg.type != MONO_TYPE_SZARRAY)) {
9370                                 MonoRgctxInfoType info_type;
9371
9372                                 if (virtual) {
9373                                         //if (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE)
9374                                                 //GSHAREDVT_FAILURE (*ip);
9375                                         // disable for possible remoting calls
9376                                         if (fsig->hasthis && (mono_class_is_marshalbyref (method->klass) || method->klass == mono_defaults.object_class))
9377                                                 GSHAREDVT_FAILURE (*ip);
9378                                         if (fsig->generic_param_count) {
9379                                                 /* virtual generic call */
9380                                                 g_assert (!imt_arg);
9381                                                 /* Same as the virtual generic case above */
9382                                                 imt_arg = emit_get_rgctx_method (cfg, context_used,
9383                                                                                                                  cmethod, MONO_RGCTX_INFO_METHOD);
9384                                                 /* This is not needed, as the trampoline code will pass one, and it might be passed in the same reg as the imt arg */
9385                                                 vtable_arg = NULL;
9386                                         } else if ((cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE) && !imt_arg) {
9387                                                 /* This can happen when we call a fully instantiated iface method */
9388                                                 imt_arg = emit_get_rgctx_method (cfg, context_used,
9389                                                                                                                  cmethod, MONO_RGCTX_INFO_METHOD);
9390                                                 vtable_arg = NULL;
9391                                         }
9392                                 }
9393
9394                                 if ((cmethod->klass->parent == mono_defaults.multicastdelegate_class) && (!strcmp (cmethod->name, "Invoke")))
9395                                         keep_this_alive = sp [0];
9396
9397                                 if (virtual && (cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL))
9398                                         info_type = MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE_VIRT;
9399                                 else
9400                                         info_type = MONO_RGCTX_INFO_METHOD_GSHAREDVT_OUT_TRAMPOLINE;
9401                                 addr = emit_get_rgctx_gsharedvt_call (cfg, context_used, fsig, cmethod, info_type);
9402
9403                                 ins = (MonoInst*)mono_emit_calli (cfg, fsig, sp, addr, imt_arg, vtable_arg);
9404                                 goto call_end;
9405                         }
9406
9407                         /* Generic sharing */
9408
9409                         /*
9410                          * Use this if the callee is gsharedvt sharable too, since
9411                          * at runtime we might find an instantiation so the call cannot
9412                          * be patched (the 'no_patch' code path in mini-trampolines.c).
9413                          */
9414                         if (context_used && !imt_arg && !array_rank && !delegate_invoke &&
9415                                 (!mono_method_is_generic_sharable_full (cmethod, TRUE, FALSE, FALSE) ||
9416                                  !mono_class_generic_sharing_enabled (cmethod->klass)) &&
9417                                 (!virtual || MONO_METHOD_IS_FINAL (cmethod) ||
9418                                  !(cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL))) {
9419                                 INLINE_FAILURE ("gshared");
9420
9421                                 g_assert (cfg->gshared && cmethod);
9422                                 g_assert (!addr);
9423
9424                                 /*
9425                                  * We are compiling a call to a
9426                                  * generic method from shared code,
9427                                  * which means that we have to look up
9428                                  * the method in the rgctx and do an
9429                                  * indirect call.
9430                                  */
9431                                 if (fsig->hasthis)
9432                                         MONO_EMIT_NEW_CHECK_THIS (cfg, sp [0]->dreg);
9433
9434                                 addr = emit_get_rgctx_method (cfg, context_used, cmethod, MONO_RGCTX_INFO_GENERIC_METHOD_CODE);
9435                                 ins = (MonoInst*)mono_emit_calli (cfg, fsig, sp, addr, imt_arg, vtable_arg);
9436                                 goto call_end;
9437                         }
9438
9439                         /* Direct calls to icalls */
9440                         if (direct_icall) {
9441                                 MonoMethod *wrapper;
9442                                 int costs;
9443
9444                                 /* Inline the wrapper */
9445                                 wrapper = mono_marshal_get_native_wrapper (cmethod, TRUE, cfg->compile_aot);
9446
9447                                 costs = inline_method (cfg, wrapper, fsig, sp, ip, cfg->real_offset, TRUE);
9448                                 g_assert (costs > 0);
9449                                 cfg->real_offset += 5;
9450
9451                                 if (!MONO_TYPE_IS_VOID (fsig->ret)) {
9452                                         /* *sp is already set by inline_method */
9453                                         sp++;
9454                                         push_res = FALSE;
9455                                 }
9456
9457                                 inline_costs += costs;
9458
9459                                 goto call_end;
9460                         }
9461                                         
9462                         /* Array methods */
9463                         if (array_rank) {
9464                                 MonoInst *addr;
9465
9466                                 if (strcmp (cmethod->name, "Set") == 0) { /* array Set */ 
9467                                         MonoInst *val = sp [fsig->param_count];
9468
9469                                         if (val->type == STACK_OBJ) {
9470                                                 MonoInst *iargs [2];
9471
9472                                                 iargs [0] = sp [0];
9473                                                 iargs [1] = val;
9474                                                 
9475                                                 mono_emit_jit_icall (cfg, mono_helper_stelem_ref_check, iargs);
9476                                         }
9477                                         
9478                                         addr = mini_emit_ldelema_ins (cfg, cmethod, sp, ip, TRUE);
9479                                         EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, fsig->params [fsig->param_count - 1], addr->dreg, 0, val->dreg);
9480                                         if (cfg->gen_write_barriers && val->type == STACK_OBJ && !(val->opcode == OP_PCONST && val->inst_c0 == 0))
9481                                                 emit_write_barrier (cfg, addr, val);
9482                                         if (cfg->gen_write_barriers && mini_is_gsharedvt_klass (cmethod->klass))
9483                                                 GSHAREDVT_FAILURE (*ip);
9484                                 } else if (strcmp (cmethod->name, "Get") == 0) { /* array Get */
9485                                         addr = mini_emit_ldelema_ins (cfg, cmethod, sp, ip, FALSE);
9486
9487                                         EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, fsig->ret, addr->dreg, 0);
9488                                 } else if (strcmp (cmethod->name, "Address") == 0) { /* array Address */
9489                                         if (!cmethod->klass->element_class->valuetype && !readonly)
9490                                                 mini_emit_check_array_type (cfg, sp [0], cmethod->klass);
9491                                         CHECK_TYPELOAD (cmethod->klass);
9492                                         
9493                                         readonly = FALSE;
9494                                         addr = mini_emit_ldelema_ins (cfg, cmethod, sp, ip, FALSE);
9495                                         ins = addr;
9496                                 } else {
9497                                         g_assert_not_reached ();
9498                                 }
9499
9500                                 emit_widen = FALSE;
9501                                 goto call_end;
9502                         }
9503
9504                         ins = mini_redirect_call (cfg, cmethod, fsig, sp, virtual ? sp [0] : NULL);
9505                         if (ins)
9506                                 goto call_end;
9507
9508                         /* Tail prefix / tail call optimization */
9509
9510                         /* FIXME: Enabling TAILC breaks some inlining/stack trace/etc tests */
9511                         /* FIXME: runtime generic context pointer for jumps? */
9512                         /* FIXME: handle this for generic sharing eventually */
9513                         if ((ins_flag & MONO_INST_TAILCALL) &&
9514                                 !vtable_arg && !cfg->gshared && is_supported_tail_call (cfg, method, cmethod, fsig, call_opcode))
9515                                 supported_tail_call = TRUE;
9516
9517                         if (supported_tail_call) {
9518                                 MonoCallInst *call;
9519
9520                                 /* Prevent inlining of methods with tail calls (the call stack would be altered) */
9521                                 INLINE_FAILURE ("tail call");
9522
9523                                 //printf ("HIT: %s -> %s\n", mono_method_full_name (cfg->method, TRUE), mono_method_full_name (cmethod, TRUE));
9524
9525                                 if (cfg->backend->have_op_tail_call) {
9526                                         /* Handle tail calls similarly to normal calls */
9527                                         tail_call = TRUE;
9528                                 } else {
9529                                         emit_instrumentation_call (cfg, mono_profiler_method_leave);
9530
9531                                         MONO_INST_NEW_CALL (cfg, call, OP_JMP);
9532                                         call->tail_call = TRUE;
9533                                         call->method = cmethod;
9534                                         call->signature = mono_method_signature (cmethod);
9535
9536                                         /*
9537                                          * We implement tail calls by storing the actual arguments into the 
9538                                          * argument variables, then emitting a CEE_JMP.
9539                                          */
9540                                         for (i = 0; i < n; ++i) {
9541                                                 /* Prevent argument from being register allocated */
9542                                                 arg_array [i]->flags |= MONO_INST_VOLATILE;
9543                                                 EMIT_NEW_ARGSTORE (cfg, ins, i, sp [i]);
9544                                         }
9545                                         ins = (MonoInst*)call;
9546                                         ins->inst_p0 = cmethod;
9547                                         ins->inst_p1 = arg_array [0];
9548                                         MONO_ADD_INS (cfg->cbb, ins);
9549                                         link_bblock (cfg, cfg->cbb, end_bblock);
9550                                         start_new_bblock = 1;
9551
9552                                         // FIXME: Eliminate unreachable epilogs
9553
9554                                         /*
9555                                          * OP_TAILCALL has no return value, so skip the CEE_RET if it is
9556                                          * only reachable from this call.
9557                                          */
9558                                         GET_BBLOCK (cfg, tblock, ip + 5);
9559                                         if (tblock == cfg->cbb || tblock->in_count == 0)
9560                                                 skip_ret = TRUE;
9561                                         push_res = FALSE;
9562
9563                                         goto call_end;
9564                                 }
9565                         }
9566
9567                         /* 
9568                          * Synchronized wrappers.
9569                          * Its hard to determine where to replace a method with its synchronized
9570                          * wrapper without causing an infinite recursion. The current solution is
9571                          * to add the synchronized wrapper in the trampolines, and to
9572                          * change the called method to a dummy wrapper, and resolve that wrapper
9573                          * to the real method in mono_jit_compile_method ().
9574                          */
9575                         if (cfg->method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED) {
9576                                 MonoMethod *orig = mono_marshal_method_from_wrapper (cfg->method);
9577                                 if (cmethod == orig || (cmethod->is_inflated && mono_method_get_declaring_generic_method (cmethod) == orig))
9578                                         cmethod = mono_marshal_get_synchronized_inner_wrapper (cmethod);
9579                         }
9580
9581                         /*
9582                          * Interface calls in llvm-only mode are complicated becase the callee might need an rgctx arg,
9583                          * (i.e. its a vtype method), and there is no way to for the caller to know this at compile time.
9584                          * So we make resolve_iface_call return the rgctx, and do two calls with different signatures
9585                          * based on whenever there is an rgctx or not.
9586                          */
9587                         if (cfg->llvm_only && virtual && cmethod && (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
9588                                 MonoInst *args [16], *icall_args [16];
9589                                 MonoBasicBlock *rgctx_bb, *end_bb;
9590                                 MonoInst *call1, *call2, *call_target;
9591                                 MonoMethodSignature *rgctx_sig;
9592                                 int rgctx_reg, tmp_reg;
9593
9594                                 MONO_EMIT_NULL_CHECK (cfg, sp [0]->dreg);
9595
9596                                 NEW_BBLOCK (cfg, rgctx_bb);
9597                                 NEW_BBLOCK (cfg, end_bb);
9598
9599                                 // FIXME: Optimize this
9600
9601                                 guint32 imt_slot = mono_method_get_imt_slot (cmethod);
9602
9603                                 icall_args [0] = sp [0];
9604                                 EMIT_NEW_ICONST (cfg, icall_args [1], imt_slot);
9605                                 if (imt_arg) {
9606                                         icall_args [2] = imt_arg;
9607                                 } else {
9608                                         EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_METHODCONST, cmethod);
9609                                         icall_args [2] = ins;
9610                                 }
9611
9612                                 rgctx_reg = alloc_preg (cfg);
9613                                 MONO_EMIT_NEW_PCONST (cfg, rgctx_reg, NULL);
9614                                 EMIT_NEW_VARLOADA_VREG (cfg, icall_args [3], rgctx_reg, &mono_defaults.int_class->byval_arg);
9615                                 //EMIT_NEW_PCONST (cfg, icall_args [3], NULL);
9616
9617                                 call_target = mono_emit_jit_icall (cfg, mono_resolve_iface_call, icall_args);
9618
9619                                 // FIXME: Only do this if needed (generic calls)
9620
9621                                 // Check whenever to pass an rgctx
9622                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, rgctx_reg, 0);
9623                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, rgctx_bb);
9624                                 /* Non rgctx case */
9625                                 call1 = mono_emit_calli (cfg, fsig, sp, call_target, NULL, vtable_arg);
9626                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
9627                                 /* Rgctx case */
9628                                 MONO_START_BB (cfg, rgctx_bb);
9629                                 /* Make a call with an rgctx */
9630                                 g_assert (fsig->param_count + 2 < 16);
9631                                 args [0] = sp [0];
9632                                 for (i = 0; i < fsig->param_count; ++i)
9633                                         args [i + 1] = sp [i + 1];
9634                                 tmp_reg = alloc_preg (cfg);
9635                                 EMIT_NEW_UNALU (cfg, args [fsig->param_count + 1], OP_MOVE, tmp_reg, rgctx_reg);
9636                                 rgctx_sig = sig_to_rgctx_sig (fsig);
9637                                 call2 = mono_emit_calli (cfg, rgctx_sig, args, call_target, NULL, NULL);
9638                                 call2->dreg = call1->dreg;
9639                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
9640                                 /* End */
9641                                 MONO_START_BB (cfg, end_bb);
9642                                 ins = call1;
9643                                 goto call_end;
9644                         }
9645
9646                         /* Common call */
9647                         INLINE_FAILURE ("call");
9648                         ins = mono_emit_method_call_full (cfg, cmethod, fsig, tail_call, sp, virtual ? sp [0] : NULL,
9649                                                                                           imt_arg, vtable_arg);
9650
9651                         if (tail_call && !cfg->llvm_only) {
9652                                 link_bblock (cfg, cfg->cbb, end_bblock);
9653                                 start_new_bblock = 1;
9654
9655                                 // FIXME: Eliminate unreachable epilogs
9656
9657                                 /*
9658                                  * OP_TAILCALL has no return value, so skip the CEE_RET if it is
9659                                  * only reachable from this call.
9660                                  */
9661                                 GET_BBLOCK (cfg, tblock, ip + 5);
9662                                 if (tblock == cfg->cbb || tblock->in_count == 0)
9663                                         skip_ret = TRUE;
9664                                 push_res = FALSE;
9665                         }
9666
9667                         call_end:
9668
9669                         /* End of call, INS should contain the result of the call, if any */
9670
9671                         if (push_res && !MONO_TYPE_IS_VOID (fsig->ret)) {
9672                                 g_assert (ins);
9673                                 if (emit_widen)
9674                                         *sp++ = mono_emit_widen_call_res (cfg, ins, fsig);
9675                                 else
9676                                         *sp++ = ins;
9677                         }
9678
9679                         if (keep_this_alive) {
9680                                 MonoInst *dummy_use;
9681
9682                                 /* See mono_emit_method_call_full () */
9683                                 EMIT_NEW_DUMMY_USE (cfg, dummy_use, keep_this_alive);
9684                         }
9685
9686                         CHECK_CFG_EXCEPTION;
9687
9688                         ip += 5;
9689                         if (skip_ret) {
9690                                 g_assert (*ip == CEE_RET);
9691                                 ip += 1;
9692                         }
9693                         ins_flag = 0;
9694                         constrained_class = NULL;
9695                         if (need_seq_point)
9696                                 emit_seq_point (cfg, method, ip, FALSE, TRUE);
9697                         break;
9698                 }
9699                 case CEE_RET:
9700                         if (cfg->method != method) {
9701                                 /* return from inlined method */
9702                                 /* 
9703                                  * If in_count == 0, that means the ret is unreachable due to
9704                                  * being preceeded by a throw. In that case, inline_method () will
9705                                  * handle setting the return value 
9706                                  * (test case: test_0_inline_throw ()).
9707                                  */
9708                                 if (return_var && cfg->cbb->in_count) {
9709                                         MonoType *ret_type = mono_method_signature (method)->ret;
9710
9711                                         MonoInst *store;
9712                                         CHECK_STACK (1);
9713                                         --sp;
9714
9715                                         if ((method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD || method->wrapper_type == MONO_WRAPPER_NONE) && target_type_is_incompatible (cfg, ret_type, *sp))
9716                                                 UNVERIFIED;
9717
9718                                         //g_assert (returnvar != -1);
9719                                         EMIT_NEW_TEMPSTORE (cfg, store, return_var->inst_c0, *sp);
9720                                         cfg->ret_var_set = TRUE;
9721                                 } 
9722                         } else {
9723                                 emit_instrumentation_call (cfg, mono_profiler_method_leave);
9724
9725                                 if (cfg->lmf_var && cfg->cbb->in_count && !cfg->llvm_only)
9726                                         emit_pop_lmf (cfg);
9727
9728                                 if (cfg->ret) {
9729                                         MonoType *ret_type = mini_get_underlying_type (mono_method_signature (method)->ret);
9730
9731                                         if (seq_points && !sym_seq_points) {
9732                                                 /* 
9733                                                  * Place a seq point here too even through the IL stack is not
9734                                                  * empty, so a step over on
9735                                                  * call <FOO>
9736                                                  * ret
9737                                                  * will work correctly.
9738                                                  */
9739                                                 NEW_SEQ_POINT (cfg, ins, ip - header->code, TRUE);
9740                                                 MONO_ADD_INS (cfg->cbb, ins);
9741                                         }
9742
9743                                         g_assert (!return_var);
9744                                         CHECK_STACK (1);
9745                                         --sp;
9746
9747                                         if ((method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD || method->wrapper_type == MONO_WRAPPER_NONE) && target_type_is_incompatible (cfg, ret_type, *sp))
9748                                                 UNVERIFIED;
9749
9750                                         emit_setret (cfg, *sp);
9751                                 }
9752                         }
9753                         if (sp != stack_start)
9754                                 UNVERIFIED;
9755                         MONO_INST_NEW (cfg, ins, OP_BR);
9756                         ip++;
9757                         ins->inst_target_bb = end_bblock;
9758                         MONO_ADD_INS (cfg->cbb, ins);
9759                         link_bblock (cfg, cfg->cbb, end_bblock);
9760                         start_new_bblock = 1;
9761                         break;
9762                 case CEE_BR_S:
9763                         CHECK_OPSIZE (2);
9764                         MONO_INST_NEW (cfg, ins, OP_BR);
9765                         ip++;
9766                         target = ip + 1 + (signed char)(*ip);
9767                         ++ip;
9768                         GET_BBLOCK (cfg, tblock, target);
9769                         link_bblock (cfg, cfg->cbb, tblock);
9770                         ins->inst_target_bb = tblock;
9771                         if (sp != stack_start) {
9772                                 handle_stack_args (cfg, stack_start, sp - stack_start);
9773                                 sp = stack_start;
9774                                 CHECK_UNVERIFIABLE (cfg);
9775                         }
9776                         MONO_ADD_INS (cfg->cbb, ins);
9777                         start_new_bblock = 1;
9778                         inline_costs += BRANCH_COST;
9779                         break;
9780                 case CEE_BEQ_S:
9781                 case CEE_BGE_S:
9782                 case CEE_BGT_S:
9783                 case CEE_BLE_S:
9784                 case CEE_BLT_S:
9785                 case CEE_BNE_UN_S:
9786                 case CEE_BGE_UN_S:
9787                 case CEE_BGT_UN_S:
9788                 case CEE_BLE_UN_S:
9789                 case CEE_BLT_UN_S:
9790                         CHECK_OPSIZE (2);
9791                         CHECK_STACK (2);
9792                         MONO_INST_NEW (cfg, ins, *ip + BIG_BRANCH_OFFSET);
9793                         ip++;
9794                         target = ip + 1 + *(signed char*)ip;
9795                         ip++;
9796
9797                         ADD_BINCOND (NULL);
9798
9799                         sp = stack_start;
9800                         inline_costs += BRANCH_COST;
9801                         break;
9802                 case CEE_BR:
9803                         CHECK_OPSIZE (5);
9804                         MONO_INST_NEW (cfg, ins, OP_BR);
9805                         ip++;
9806
9807                         target = ip + 4 + (gint32)read32(ip);
9808                         ip += 4;
9809                         GET_BBLOCK (cfg, tblock, target);
9810                         link_bblock (cfg, cfg->cbb, tblock);
9811                         ins->inst_target_bb = tblock;
9812                         if (sp != stack_start) {
9813                                 handle_stack_args (cfg, stack_start, sp - stack_start);
9814                                 sp = stack_start;
9815                                 CHECK_UNVERIFIABLE (cfg);
9816                         }
9817
9818                         MONO_ADD_INS (cfg->cbb, ins);
9819
9820                         start_new_bblock = 1;
9821                         inline_costs += BRANCH_COST;
9822                         break;
9823                 case CEE_BRFALSE_S:
9824                 case CEE_BRTRUE_S:
9825                 case CEE_BRFALSE:
9826                 case CEE_BRTRUE: {
9827                         MonoInst *cmp;
9828                         gboolean is_short = ((*ip) == CEE_BRFALSE_S) || ((*ip) == CEE_BRTRUE_S);
9829                         gboolean is_true = ((*ip) == CEE_BRTRUE_S) || ((*ip) == CEE_BRTRUE);
9830                         guint32 opsize = is_short ? 1 : 4;
9831
9832                         CHECK_OPSIZE (opsize);
9833                         CHECK_STACK (1);
9834                         if (sp [-1]->type == STACK_VTYPE || sp [-1]->type == STACK_R8)
9835                                 UNVERIFIED;
9836                         ip ++;
9837                         target = ip + opsize + (is_short ? *(signed char*)ip : (gint32)read32(ip));
9838                         ip += opsize;
9839
9840                         sp--;
9841
9842                         GET_BBLOCK (cfg, tblock, target);
9843                         link_bblock (cfg, cfg->cbb, tblock);
9844                         GET_BBLOCK (cfg, tblock, ip);
9845                         link_bblock (cfg, cfg->cbb, tblock);
9846
9847                         if (sp != stack_start) {
9848                                 handle_stack_args (cfg, stack_start, sp - stack_start);
9849                                 CHECK_UNVERIFIABLE (cfg);
9850                         }
9851
9852                         MONO_INST_NEW(cfg, cmp, OP_ICOMPARE_IMM);
9853                         cmp->sreg1 = sp [0]->dreg;
9854                         type_from_op (cfg, cmp, sp [0], NULL);
9855                         CHECK_TYPE (cmp);
9856
9857 #if SIZEOF_REGISTER == 4
9858                         if (cmp->opcode == OP_LCOMPARE_IMM) {
9859                                 /* Convert it to OP_LCOMPARE */
9860                                 MONO_INST_NEW (cfg, ins, OP_I8CONST);
9861                                 ins->type = STACK_I8;
9862                                 ins->dreg = alloc_dreg (cfg, STACK_I8);
9863                                 ins->inst_l = 0;
9864                                 MONO_ADD_INS (cfg->cbb, ins);
9865                                 cmp->opcode = OP_LCOMPARE;
9866                                 cmp->sreg2 = ins->dreg;
9867                         }
9868 #endif
9869                         MONO_ADD_INS (cfg->cbb, cmp);
9870
9871                         MONO_INST_NEW (cfg, ins, is_true ? CEE_BNE_UN : CEE_BEQ);
9872                         type_from_op (cfg, ins, sp [0], NULL);
9873                         MONO_ADD_INS (cfg->cbb, ins);
9874                         ins->inst_many_bb = mono_mempool_alloc (cfg->mempool, sizeof(gpointer)*2);
9875                         GET_BBLOCK (cfg, tblock, target);
9876                         ins->inst_true_bb = tblock;
9877                         GET_BBLOCK (cfg, tblock, ip);
9878                         ins->inst_false_bb = tblock;
9879                         start_new_bblock = 2;
9880
9881                         sp = stack_start;
9882                         inline_costs += BRANCH_COST;
9883                         break;
9884                 }
9885                 case CEE_BEQ:
9886                 case CEE_BGE:
9887                 case CEE_BGT:
9888                 case CEE_BLE:
9889                 case CEE_BLT:
9890                 case CEE_BNE_UN:
9891                 case CEE_BGE_UN:
9892                 case CEE_BGT_UN:
9893                 case CEE_BLE_UN:
9894                 case CEE_BLT_UN:
9895                         CHECK_OPSIZE (5);
9896                         CHECK_STACK (2);
9897                         MONO_INST_NEW (cfg, ins, *ip);
9898                         ip++;
9899                         target = ip + 4 + (gint32)read32(ip);
9900                         ip += 4;
9901
9902                         ADD_BINCOND (NULL);
9903
9904                         sp = stack_start;
9905                         inline_costs += BRANCH_COST;
9906                         break;
9907                 case CEE_SWITCH: {
9908                         MonoInst *src1;
9909                         MonoBasicBlock **targets;
9910                         MonoBasicBlock *default_bblock;
9911                         MonoJumpInfoBBTable *table;
9912                         int offset_reg = alloc_preg (cfg);
9913                         int target_reg = alloc_preg (cfg);
9914                         int table_reg = alloc_preg (cfg);
9915                         int sum_reg = alloc_preg (cfg);
9916                         gboolean use_op_switch;
9917
9918                         CHECK_OPSIZE (5);
9919                         CHECK_STACK (1);
9920                         n = read32 (ip + 1);
9921                         --sp;
9922                         src1 = sp [0];
9923                         if ((src1->type != STACK_I4) && (src1->type != STACK_PTR)) 
9924                                 UNVERIFIED;
9925
9926                         ip += 5;
9927                         CHECK_OPSIZE (n * sizeof (guint32));
9928                         target = ip + n * sizeof (guint32);
9929
9930                         GET_BBLOCK (cfg, default_bblock, target);
9931                         default_bblock->flags |= BB_INDIRECT_JUMP_TARGET;
9932
9933                         targets = mono_mempool_alloc (cfg->mempool, sizeof (MonoBasicBlock*) * n);
9934                         for (i = 0; i < n; ++i) {
9935                                 GET_BBLOCK (cfg, tblock, target + (gint32)read32(ip));
9936                                 targets [i] = tblock;
9937                                 targets [i]->flags |= BB_INDIRECT_JUMP_TARGET;
9938                                 ip += 4;
9939                         }
9940
9941                         if (sp != stack_start) {
9942                                 /* 
9943                                  * Link the current bb with the targets as well, so handle_stack_args
9944                                  * will set their in_stack correctly.
9945                                  */
9946                                 link_bblock (cfg, cfg->cbb, default_bblock);
9947                                 for (i = 0; i < n; ++i)
9948                                         link_bblock (cfg, cfg->cbb, targets [i]);
9949
9950                                 handle_stack_args (cfg, stack_start, sp - stack_start);
9951                                 sp = stack_start;
9952                                 CHECK_UNVERIFIABLE (cfg);
9953
9954                                 /* Undo the links */
9955                                 mono_unlink_bblock (cfg, cfg->cbb, default_bblock);
9956                                 for (i = 0; i < n; ++i)
9957                                         mono_unlink_bblock (cfg, cfg->cbb, targets [i]);
9958                         }
9959
9960                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, src1->dreg, n);
9961                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBGE_UN, default_bblock);
9962
9963                         for (i = 0; i < n; ++i)
9964                                 link_bblock (cfg, cfg->cbb, targets [i]);
9965
9966                         table = mono_mempool_alloc (cfg->mempool, sizeof (MonoJumpInfoBBTable));
9967                         table->table = targets;
9968                         table->table_size = n;
9969
9970                         use_op_switch = FALSE;
9971 #ifdef TARGET_ARM
9972                         /* ARM implements SWITCH statements differently */
9973                         /* FIXME: Make it use the generic implementation */
9974                         if (!cfg->compile_aot)
9975                                 use_op_switch = TRUE;
9976 #endif
9977
9978                         if (COMPILE_LLVM (cfg))
9979                                 use_op_switch = TRUE;
9980
9981                         cfg->cbb->has_jump_table = 1;
9982
9983                         if (use_op_switch) {
9984                                 MONO_INST_NEW (cfg, ins, OP_SWITCH);
9985                                 ins->sreg1 = src1->dreg;
9986                                 ins->inst_p0 = table;
9987                                 ins->inst_many_bb = targets;
9988                                 ins->klass = GUINT_TO_POINTER (n);
9989                                 MONO_ADD_INS (cfg->cbb, ins);
9990                         } else {
9991                                 if (sizeof (gpointer) == 8)
9992                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHL_IMM, offset_reg, src1->dreg, 3);
9993                                 else
9994                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHL_IMM, offset_reg, src1->dreg, 2);
9995
9996 #if SIZEOF_REGISTER == 8
9997                                 /* The upper word might not be zero, and we add it to a 64 bit address later */
9998                                 MONO_EMIT_NEW_UNALU (cfg, OP_ZEXT_I4, offset_reg, offset_reg);
9999 #endif
10000
10001                                 if (cfg->compile_aot) {
10002                                         MONO_EMIT_NEW_AOTCONST (cfg, table_reg, table, MONO_PATCH_INFO_SWITCH);
10003                                 } else {
10004                                         MONO_INST_NEW (cfg, ins, OP_JUMP_TABLE);
10005                                         ins->inst_c1 = MONO_PATCH_INFO_SWITCH;
10006                                         ins->inst_p0 = table;
10007                                         ins->dreg = table_reg;
10008                                         MONO_ADD_INS (cfg->cbb, ins);
10009                                 }
10010
10011                                 /* FIXME: Use load_memindex */
10012                                 MONO_EMIT_NEW_BIALU (cfg, OP_PADD, sum_reg, table_reg, offset_reg);
10013                                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, target_reg, sum_reg, 0);
10014                                 MONO_EMIT_NEW_UNALU (cfg, OP_BR_REG, -1, target_reg);
10015                         }
10016                         start_new_bblock = 1;
10017                         inline_costs += (BRANCH_COST * 2);
10018                         break;
10019                 }
10020                 case CEE_LDIND_I1:
10021                 case CEE_LDIND_U1:
10022                 case CEE_LDIND_I2:
10023                 case CEE_LDIND_U2:
10024                 case CEE_LDIND_I4:
10025                 case CEE_LDIND_U4:
10026                 case CEE_LDIND_I8:
10027                 case CEE_LDIND_I:
10028                 case CEE_LDIND_R4:
10029                 case CEE_LDIND_R8:
10030                 case CEE_LDIND_REF:
10031                         CHECK_STACK (1);
10032                         --sp;
10033
10034                         switch (*ip) {
10035                         case CEE_LDIND_R4:
10036                         case CEE_LDIND_R8:
10037                                 dreg = alloc_freg (cfg);
10038                                 break;
10039                         case CEE_LDIND_I8:
10040                                 dreg = alloc_lreg (cfg);
10041                                 break;
10042                         case CEE_LDIND_REF:
10043                                 dreg = alloc_ireg_ref (cfg);
10044                                 break;
10045                         default:
10046                                 dreg = alloc_preg (cfg);
10047                         }
10048
10049                         NEW_LOAD_MEMBASE (cfg, ins, ldind_to_load_membase (*ip), dreg, sp [0]->dreg, 0);
10050                         ins->type = ldind_type [*ip - CEE_LDIND_I1];
10051                         if (*ip == CEE_LDIND_R4)
10052                                 ins->type = cfg->r4_stack_type;
10053                         ins->flags |= ins_flag;
10054                         MONO_ADD_INS (cfg->cbb, ins);
10055                         *sp++ = ins;
10056                         if (ins_flag & MONO_INST_VOLATILE) {
10057                                 /* Volatile loads have acquire semantics, see 12.6.7 in Ecma 335 */
10058                                 emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_ACQ);
10059                         }
10060                         ins_flag = 0;
10061                         ++ip;
10062                         break;
10063                 case CEE_STIND_REF:
10064                 case CEE_STIND_I1:
10065                 case CEE_STIND_I2:
10066                 case CEE_STIND_I4:
10067                 case CEE_STIND_I8:
10068                 case CEE_STIND_R4:
10069                 case CEE_STIND_R8:
10070                 case CEE_STIND_I:
10071                         CHECK_STACK (2);
10072                         sp -= 2;
10073
10074                         if (ins_flag & MONO_INST_VOLATILE) {
10075                                 /* Volatile stores have release semantics, see 12.6.7 in Ecma 335 */
10076                                 emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL);
10077                         }
10078
10079                         NEW_STORE_MEMBASE (cfg, ins, stind_to_store_membase (*ip), sp [0]->dreg, 0, sp [1]->dreg);
10080                         ins->flags |= ins_flag;
10081                         ins_flag = 0;
10082
10083                         MONO_ADD_INS (cfg->cbb, ins);
10084
10085                         if (cfg->gen_write_barriers && *ip == CEE_STIND_REF && method->wrapper_type != MONO_WRAPPER_WRITE_BARRIER && !((sp [1]->opcode == OP_PCONST) && (sp [1]->inst_p0 == 0)))
10086                                 emit_write_barrier (cfg, sp [0], sp [1]);
10087
10088                         inline_costs += 1;
10089                         ++ip;
10090                         break;
10091
10092                 case CEE_MUL:
10093                         CHECK_STACK (2);
10094
10095                         MONO_INST_NEW (cfg, ins, (*ip));
10096                         sp -= 2;
10097                         ins->sreg1 = sp [0]->dreg;
10098                         ins->sreg2 = sp [1]->dreg;
10099                         type_from_op (cfg, ins, sp [0], sp [1]);
10100                         CHECK_TYPE (ins);
10101                         ins->dreg = alloc_dreg ((cfg), (ins)->type);
10102
10103                         /* Use the immediate opcodes if possible */
10104                         if ((sp [1]->opcode == OP_ICONST) && mono_arch_is_inst_imm (sp [1]->inst_c0)) {
10105                                 int imm_opcode = mono_op_to_op_imm_noemul (ins->opcode);
10106                                 if (imm_opcode != -1) {
10107                                         ins->opcode = imm_opcode;
10108                                         ins->inst_p1 = (gpointer)(gssize)(sp [1]->inst_c0);
10109                                         ins->sreg2 = -1;
10110
10111                                         NULLIFY_INS (sp [1]);
10112                                 }
10113                         }
10114
10115                         MONO_ADD_INS ((cfg)->cbb, (ins));
10116
10117                         *sp++ = mono_decompose_opcode (cfg, ins);
10118                         ip++;
10119                         break;
10120                 case CEE_ADD:
10121                 case CEE_SUB:
10122                 case CEE_DIV:
10123                 case CEE_DIV_UN:
10124                 case CEE_REM:
10125                 case CEE_REM_UN:
10126                 case CEE_AND:
10127                 case CEE_OR:
10128                 case CEE_XOR:
10129                 case CEE_SHL:
10130                 case CEE_SHR:
10131                 case CEE_SHR_UN:
10132                         CHECK_STACK (2);
10133
10134                         MONO_INST_NEW (cfg, ins, (*ip));
10135                         sp -= 2;
10136                         ins->sreg1 = sp [0]->dreg;
10137                         ins->sreg2 = sp [1]->dreg;
10138                         type_from_op (cfg, ins, sp [0], sp [1]);
10139                         CHECK_TYPE (ins);
10140                         add_widen_op (cfg, ins, &sp [0], &sp [1]);
10141                         ins->dreg = alloc_dreg ((cfg), (ins)->type);
10142
10143                         /* FIXME: Pass opcode to is_inst_imm */
10144
10145                         /* Use the immediate opcodes if possible */
10146                         if (((sp [1]->opcode == OP_ICONST) || (sp [1]->opcode == OP_I8CONST)) && mono_arch_is_inst_imm (sp [1]->opcode == OP_ICONST ? sp [1]->inst_c0 : sp [1]->inst_l)) {
10147                                 int imm_opcode;
10148
10149                                 imm_opcode = mono_op_to_op_imm_noemul (ins->opcode);
10150 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV)
10151                                 /* Keep emulated opcodes which are optimized away later */
10152                                 if ((ins->opcode == OP_IREM_UN || ins->opcode == OP_IDIV_UN_IMM) && (cfg->opt & (MONO_OPT_CONSPROP | MONO_OPT_COPYPROP)) && sp [1]->opcode == OP_ICONST && mono_is_power_of_two (sp [1]->inst_c0) >= 0) {
10153                                         imm_opcode = mono_op_to_op_imm (ins->opcode);
10154                                 }
10155 #endif
10156                                 if (imm_opcode != -1) {
10157                                         ins->opcode = imm_opcode;
10158                                         if (sp [1]->opcode == OP_I8CONST) {
10159 #if SIZEOF_REGISTER == 8
10160                                                 ins->inst_imm = sp [1]->inst_l;
10161 #else
10162                                                 ins->inst_ls_word = sp [1]->inst_ls_word;
10163                                                 ins->inst_ms_word = sp [1]->inst_ms_word;
10164 #endif
10165                                         }
10166                                         else
10167                                                 ins->inst_imm = (gssize)(sp [1]->inst_c0);
10168                                         ins->sreg2 = -1;
10169
10170                                         /* Might be followed by an instruction added by add_widen_op */
10171                                         if (sp [1]->next == NULL)
10172                                                 NULLIFY_INS (sp [1]);
10173                                 }
10174                         }
10175                         MONO_ADD_INS ((cfg)->cbb, (ins));
10176
10177                         *sp++ = mono_decompose_opcode (cfg, ins);
10178                         ip++;
10179                         break;
10180                 case CEE_NEG:
10181                 case CEE_NOT:
10182                 case CEE_CONV_I1:
10183                 case CEE_CONV_I2:
10184                 case CEE_CONV_I4:
10185                 case CEE_CONV_R4:
10186                 case CEE_CONV_R8:
10187                 case CEE_CONV_U4:
10188                 case CEE_CONV_I8:
10189                 case CEE_CONV_U8:
10190                 case CEE_CONV_OVF_I8:
10191                 case CEE_CONV_OVF_U8:
10192                 case CEE_CONV_R_UN:
10193                         CHECK_STACK (1);
10194
10195                         /* Special case this earlier so we have long constants in the IR */
10196                         if ((((*ip) == CEE_CONV_I8) || ((*ip) == CEE_CONV_U8)) && (sp [-1]->opcode == OP_ICONST)) {
10197                                 int data = sp [-1]->inst_c0;
10198                                 sp [-1]->opcode = OP_I8CONST;
10199                                 sp [-1]->type = STACK_I8;
10200 #if SIZEOF_REGISTER == 8
10201                                 if ((*ip) == CEE_CONV_U8)
10202                                         sp [-1]->inst_c0 = (guint32)data;
10203                                 else
10204                                         sp [-1]->inst_c0 = data;
10205 #else
10206                                 sp [-1]->inst_ls_word = data;
10207                                 if ((*ip) == CEE_CONV_U8)
10208                                         sp [-1]->inst_ms_word = 0;
10209                                 else
10210                                         sp [-1]->inst_ms_word = (data < 0) ? -1 : 0;
10211 #endif
10212                                 sp [-1]->dreg = alloc_dreg (cfg, STACK_I8);
10213                         }
10214                         else {
10215                                 ADD_UNOP (*ip);
10216                         }
10217                         ip++;
10218                         break;
10219                 case CEE_CONV_OVF_I4:
10220                 case CEE_CONV_OVF_I1:
10221                 case CEE_CONV_OVF_I2:
10222                 case CEE_CONV_OVF_I:
10223                 case CEE_CONV_OVF_U:
10224                         CHECK_STACK (1);
10225
10226                         if (sp [-1]->type == STACK_R8 || sp [-1]->type == STACK_R4) {
10227                                 ADD_UNOP (CEE_CONV_OVF_I8);
10228                                 ADD_UNOP (*ip);
10229                         } else {
10230                                 ADD_UNOP (*ip);
10231                         }
10232                         ip++;
10233                         break;
10234                 case CEE_CONV_OVF_U1:
10235                 case CEE_CONV_OVF_U2:
10236                 case CEE_CONV_OVF_U4:
10237                         CHECK_STACK (1);
10238
10239                         if (sp [-1]->type == STACK_R8 || sp [-1]->type == STACK_R4) {
10240                                 ADD_UNOP (CEE_CONV_OVF_U8);
10241                                 ADD_UNOP (*ip);
10242                         } else {
10243                                 ADD_UNOP (*ip);
10244                         }
10245                         ip++;
10246                         break;
10247                 case CEE_CONV_OVF_I1_UN:
10248                 case CEE_CONV_OVF_I2_UN:
10249                 case CEE_CONV_OVF_I4_UN:
10250                 case CEE_CONV_OVF_I8_UN:
10251                 case CEE_CONV_OVF_U1_UN:
10252                 case CEE_CONV_OVF_U2_UN:
10253                 case CEE_CONV_OVF_U4_UN:
10254                 case CEE_CONV_OVF_U8_UN:
10255                 case CEE_CONV_OVF_I_UN:
10256                 case CEE_CONV_OVF_U_UN:
10257                 case CEE_CONV_U2:
10258                 case CEE_CONV_U1:
10259                 case CEE_CONV_I:
10260                 case CEE_CONV_U:
10261                         CHECK_STACK (1);
10262                         ADD_UNOP (*ip);
10263                         CHECK_CFG_EXCEPTION;
10264                         ip++;
10265                         break;
10266                 case CEE_ADD_OVF:
10267                 case CEE_ADD_OVF_UN:
10268                 case CEE_MUL_OVF:
10269                 case CEE_MUL_OVF_UN:
10270                 case CEE_SUB_OVF:
10271                 case CEE_SUB_OVF_UN:
10272                         CHECK_STACK (2);
10273                         ADD_BINOP (*ip);
10274                         ip++;
10275                         break;
10276                 case CEE_CPOBJ:
10277                         GSHAREDVT_FAILURE (*ip);
10278                         CHECK_OPSIZE (5);
10279                         CHECK_STACK (2);
10280                         token = read32 (ip + 1);
10281                         klass = mini_get_class (method, token, generic_context);
10282                         CHECK_TYPELOAD (klass);
10283                         sp -= 2;
10284                         if (generic_class_is_reference_type (cfg, klass)) {
10285                                 MonoInst *store, *load;
10286                                 int dreg = alloc_ireg_ref (cfg);
10287
10288                                 NEW_LOAD_MEMBASE (cfg, load, OP_LOAD_MEMBASE, dreg, sp [1]->dreg, 0);
10289                                 load->flags |= ins_flag;
10290                                 MONO_ADD_INS (cfg->cbb, load);
10291
10292                                 NEW_STORE_MEMBASE (cfg, store, OP_STORE_MEMBASE_REG, sp [0]->dreg, 0, dreg);
10293                                 store->flags |= ins_flag;
10294                                 MONO_ADD_INS (cfg->cbb, store);
10295
10296                                 if (cfg->gen_write_barriers && cfg->method->wrapper_type != MONO_WRAPPER_WRITE_BARRIER)
10297                                         emit_write_barrier (cfg, sp [0], sp [1]);
10298                         } else {
10299                                 mini_emit_stobj (cfg, sp [0], sp [1], klass, FALSE);
10300                         }
10301                         ins_flag = 0;
10302                         ip += 5;
10303                         break;
10304                 case CEE_LDOBJ: {
10305                         int loc_index = -1;
10306                         int stloc_len = 0;
10307
10308                         CHECK_OPSIZE (5);
10309                         CHECK_STACK (1);
10310                         --sp;
10311                         token = read32 (ip + 1);
10312                         klass = mini_get_class (method, token, generic_context);
10313                         CHECK_TYPELOAD (klass);
10314
10315                         /* Optimize the common ldobj+stloc combination */
10316                         switch (ip [5]) {
10317                         case CEE_STLOC_S:
10318                                 loc_index = ip [6];
10319                                 stloc_len = 2;
10320                                 break;
10321                         case CEE_STLOC_0:
10322                         case CEE_STLOC_1:
10323                         case CEE_STLOC_2:
10324                         case CEE_STLOC_3:
10325                                 loc_index = ip [5] - CEE_STLOC_0;
10326                                 stloc_len = 1;
10327                                 break;
10328                         default:
10329                                 break;
10330                         }
10331
10332                         if ((loc_index != -1) && ip_in_bb (cfg, cfg->cbb, ip + 5)) {
10333                                 CHECK_LOCAL (loc_index);
10334
10335                                 EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, sp [0]->dreg, 0);
10336                                 ins->dreg = cfg->locals [loc_index]->dreg;
10337                                 ins->flags |= ins_flag;
10338                                 ip += 5;
10339                                 ip += stloc_len;
10340                                 if (ins_flag & MONO_INST_VOLATILE) {
10341                                         /* Volatile loads have acquire semantics, see 12.6.7 in Ecma 335 */
10342                                         emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_ACQ);
10343                                 }
10344                                 ins_flag = 0;
10345                                 break;
10346                         }
10347
10348                         /* Optimize the ldobj+stobj combination */
10349                         /* The reference case ends up being a load+store anyway */
10350                         /* Skip this if the operation is volatile. */
10351                         if (((ip [5] == CEE_STOBJ) && ip_in_bb (cfg, cfg->cbb, ip + 5) && read32 (ip + 6) == token) && !generic_class_is_reference_type (cfg, klass) && !(ins_flag & MONO_INST_VOLATILE)) {
10352                                 CHECK_STACK (1);
10353
10354                                 sp --;
10355
10356                                 mini_emit_stobj (cfg, sp [0], sp [1], klass, FALSE);
10357
10358                                 ip += 5 + 5;
10359                                 ins_flag = 0;
10360                                 break;
10361                         }
10362
10363                         EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, sp [0]->dreg, 0);
10364                         ins->flags |= ins_flag;
10365                         *sp++ = ins;
10366
10367                         if (ins_flag & MONO_INST_VOLATILE) {
10368                                 /* Volatile loads have acquire semantics, see 12.6.7 in Ecma 335 */
10369                                 emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_ACQ);
10370                         }
10371
10372                         ip += 5;
10373                         ins_flag = 0;
10374                         inline_costs += 1;
10375                         break;
10376                 }
10377                 case CEE_LDSTR:
10378                         CHECK_STACK_OVF (1);
10379                         CHECK_OPSIZE (5);
10380                         n = read32 (ip + 1);
10381
10382                         if (method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD) {
10383                                 EMIT_NEW_PCONST (cfg, ins, mono_method_get_wrapper_data (method, n));
10384                                 ins->type = STACK_OBJ;
10385                                 *sp = ins;
10386                         }
10387                         else if (method->wrapper_type != MONO_WRAPPER_NONE) {
10388                                 MonoInst *iargs [1];
10389                                 char *str = mono_method_get_wrapper_data (method, n);
10390
10391                                 if (cfg->compile_aot)
10392                                         EMIT_NEW_LDSTRLITCONST (cfg, iargs [0], str);
10393                                 else
10394                                         EMIT_NEW_PCONST (cfg, iargs [0], str);
10395                                 *sp = mono_emit_jit_icall (cfg, mono_string_new_wrapper, iargs);
10396                         } else {
10397                                 if (cfg->opt & MONO_OPT_SHARED) {
10398                                         MonoInst *iargs [3];
10399
10400                                         if (cfg->compile_aot) {
10401                                                 cfg->ldstr_list = g_list_prepend (cfg->ldstr_list, GINT_TO_POINTER (n));
10402                                         }
10403                                         EMIT_NEW_DOMAINCONST (cfg, iargs [0]);
10404                                         EMIT_NEW_IMAGECONST (cfg, iargs [1], image);
10405                                         EMIT_NEW_ICONST (cfg, iargs [2], mono_metadata_token_index (n));
10406                                         *sp = mono_emit_jit_icall (cfg, mono_ldstr, iargs);
10407                                         mono_ldstr (cfg->domain, image, mono_metadata_token_index (n));
10408                                 } else {
10409                                         if (cfg->cbb->out_of_line) {
10410                                                 MonoInst *iargs [2];
10411
10412                                                 if (image == mono_defaults.corlib) {
10413                                                         /* 
10414                                                          * Avoid relocations in AOT and save some space by using a 
10415                                                          * version of helper_ldstr specialized to mscorlib.
10416                                                          */
10417                                                         EMIT_NEW_ICONST (cfg, iargs [0], mono_metadata_token_index (n));
10418                                                         *sp = mono_emit_jit_icall (cfg, mono_helper_ldstr_mscorlib, iargs);
10419                                                 } else {
10420                                                         /* Avoid creating the string object */
10421                                                         EMIT_NEW_IMAGECONST (cfg, iargs [0], image);
10422                                                         EMIT_NEW_ICONST (cfg, iargs [1], mono_metadata_token_index (n));
10423                                                         *sp = mono_emit_jit_icall (cfg, mono_helper_ldstr, iargs);
10424                                                 }
10425                                         } 
10426                                         else
10427                                         if (cfg->compile_aot) {
10428                                                 NEW_LDSTRCONST (cfg, ins, image, n);
10429                                                 *sp = ins;
10430                                                 MONO_ADD_INS (cfg->cbb, ins);
10431                                         } 
10432                                         else {
10433                                                 NEW_PCONST (cfg, ins, NULL);
10434                                                 ins->type = STACK_OBJ;
10435                                                 ins->inst_p0 = mono_ldstr (cfg->domain, image, mono_metadata_token_index (n));
10436                                                 if (!ins->inst_p0)
10437                                                         OUT_OF_MEMORY_FAILURE;
10438
10439                                                 *sp = ins;
10440                                                 MONO_ADD_INS (cfg->cbb, ins);
10441                                         }
10442                                 }
10443                         }
10444
10445                         sp++;
10446                         ip += 5;
10447                         break;
10448                 case CEE_NEWOBJ: {
10449                         MonoInst *iargs [2];
10450                         MonoMethodSignature *fsig;
10451                         MonoInst this_ins;
10452                         MonoInst *alloc;
10453                         MonoInst *vtable_arg = NULL;
10454
10455                         CHECK_OPSIZE (5);
10456                         token = read32 (ip + 1);
10457                         cmethod = mini_get_method (cfg, method, token, NULL, generic_context);
10458                         if (!cmethod || mono_loader_get_last_error ())
10459                                 LOAD_ERROR;
10460                         fsig = mono_method_get_signature_checked (cmethod, image, token, generic_context, &cfg->error);
10461                         CHECK_CFG_ERROR;
10462
10463                         mono_save_token_info (cfg, image, token, cmethod);
10464
10465                         if (!mono_class_init (cmethod->klass))
10466                                 TYPE_LOAD_ERROR (cmethod->klass);
10467
10468                         context_used = mini_method_check_context_used (cfg, cmethod);
10469
10470                         if (mono_security_core_clr_enabled ())
10471                                 ensure_method_is_allowed_to_call_method (cfg, method, cmethod);
10472
10473                         if (cfg->gshared && cmethod && cmethod->klass != method->klass && cmethod->klass->generic_class && mono_method_is_generic_sharable (cmethod, TRUE) && mono_class_needs_cctor_run (cmethod->klass, method)) {
10474                                 emit_class_init (cfg, cmethod->klass);
10475                                 CHECK_TYPELOAD (cmethod->klass);
10476                         }
10477
10478                         /*
10479                         if (cfg->gsharedvt) {
10480                                 if (mini_is_gsharedvt_variable_signature (sig))
10481                                         GSHAREDVT_FAILURE (*ip);
10482                         }
10483                         */
10484
10485                         n = fsig->param_count;
10486                         CHECK_STACK (n);
10487
10488                         /* 
10489                          * Generate smaller code for the common newobj <exception> instruction in
10490                          * argument checking code.
10491                          */
10492                         if (cfg->cbb->out_of_line && cmethod->klass->image == mono_defaults.corlib &&
10493                                 is_exception_class (cmethod->klass) && n <= 2 &&
10494                                 ((n < 1) || (!fsig->params [0]->byref && fsig->params [0]->type == MONO_TYPE_STRING)) && 
10495                                 ((n < 2) || (!fsig->params [1]->byref && fsig->params [1]->type == MONO_TYPE_STRING))) {
10496                                 MonoInst *iargs [3];
10497
10498                                 sp -= n;
10499
10500                                 EMIT_NEW_ICONST (cfg, iargs [0], cmethod->klass->type_token);
10501                                 switch (n) {
10502                                 case 0:
10503                                         *sp ++ = mono_emit_jit_icall (cfg, mono_create_corlib_exception_0, iargs);
10504                                         break;
10505                                 case 1:
10506                                         iargs [1] = sp [0];
10507                                         *sp ++ = mono_emit_jit_icall (cfg, mono_create_corlib_exception_1, iargs);
10508                                         break;
10509                                 case 2:
10510                                         iargs [1] = sp [0];
10511                                         iargs [2] = sp [1];
10512                                         *sp ++ = mono_emit_jit_icall (cfg, mono_create_corlib_exception_2, iargs);
10513                                         break;
10514                                 default:
10515                                         g_assert_not_reached ();
10516                                 }
10517
10518                                 ip += 5;
10519                                 inline_costs += 5;
10520                                 break;
10521                         }
10522
10523                         /* move the args to allow room for 'this' in the first position */
10524                         while (n--) {
10525                                 --sp;
10526                                 sp [1] = sp [0];
10527                         }
10528
10529                         /* check_call_signature () requires sp[0] to be set */
10530                         this_ins.type = STACK_OBJ;
10531                         sp [0] = &this_ins;
10532                         if (check_call_signature (cfg, fsig, sp))
10533                                 UNVERIFIED;
10534
10535                         iargs [0] = NULL;
10536
10537                         if (mini_class_is_system_array (cmethod->klass)) {
10538                                 *sp = emit_get_rgctx_method (cfg, context_used,
10539                                                                                          cmethod, MONO_RGCTX_INFO_METHOD);
10540
10541                                 /* Avoid varargs in the common case */
10542                                 if (fsig->param_count == 1)
10543                                         alloc = mono_emit_jit_icall (cfg, mono_array_new_1, sp);
10544                                 else if (fsig->param_count == 2)
10545                                         alloc = mono_emit_jit_icall (cfg, mono_array_new_2, sp);
10546                                 else if (fsig->param_count == 3)
10547                                         alloc = mono_emit_jit_icall (cfg, mono_array_new_3, sp);
10548                                 else if (fsig->param_count == 4)
10549                                         alloc = mono_emit_jit_icall (cfg, mono_array_new_4, sp);
10550                                 else
10551                                         alloc = handle_array_new (cfg, fsig->param_count, sp, ip);
10552                         } else if (cmethod->string_ctor) {
10553                                 g_assert (!context_used);
10554                                 g_assert (!vtable_arg);
10555                                 /* we simply pass a null pointer */
10556                                 EMIT_NEW_PCONST (cfg, *sp, NULL); 
10557                                 /* now call the string ctor */
10558                                 alloc = mono_emit_method_call_full (cfg, cmethod, fsig, FALSE, sp, NULL, NULL, NULL);
10559                         } else {
10560                                 if (cmethod->klass->valuetype) {
10561                                         iargs [0] = mono_compile_create_var (cfg, &cmethod->klass->byval_arg, OP_LOCAL);
10562                                         emit_init_rvar (cfg, iargs [0]->dreg, &cmethod->klass->byval_arg);
10563                                         EMIT_NEW_TEMPLOADA (cfg, *sp, iargs [0]->inst_c0);
10564
10565                                         alloc = NULL;
10566
10567                                         /* 
10568                                          * The code generated by mini_emit_virtual_call () expects
10569                                          * iargs [0] to be a boxed instance, but luckily the vcall
10570                                          * will be transformed into a normal call there.
10571                                          */
10572                                 } else if (context_used) {
10573                                         alloc = handle_alloc (cfg, cmethod->klass, FALSE, context_used);
10574                                         *sp = alloc;
10575                                 } else {
10576                                         MonoVTable *vtable = NULL;
10577
10578                                         if (!cfg->compile_aot)
10579                                                 vtable = mono_class_vtable (cfg->domain, cmethod->klass);
10580                                         CHECK_TYPELOAD (cmethod->klass);
10581
10582                                         /*
10583                                          * TypeInitializationExceptions thrown from the mono_runtime_class_init
10584                                          * call in mono_jit_runtime_invoke () can abort the finalizer thread.
10585                                          * As a workaround, we call class cctors before allocating objects.
10586                                          */
10587                                         if (mini_field_access_needs_cctor_run (cfg, method, cmethod->klass, vtable) && !(g_slist_find (class_inits, cmethod->klass))) {
10588                                                 emit_class_init (cfg, cmethod->klass);
10589                                                 if (cfg->verbose_level > 2)
10590                                                         printf ("class %s.%s needs init call for ctor\n", cmethod->klass->name_space, cmethod->klass->name);
10591                                                 class_inits = g_slist_prepend (class_inits, cmethod->klass);
10592                                         }
10593
10594                                         alloc = handle_alloc (cfg, cmethod->klass, FALSE, 0);
10595                                         *sp = alloc;
10596                                 }
10597                                 CHECK_CFG_EXCEPTION; /*for handle_alloc*/
10598
10599                                 if (alloc)
10600                                         MONO_EMIT_NEW_UNALU (cfg, OP_NOT_NULL, -1, alloc->dreg);
10601
10602                                 /* Now call the actual ctor */
10603                                 handle_ctor_call (cfg, cmethod, fsig, context_used, sp, ip, &inline_costs);
10604                                 CHECK_CFG_EXCEPTION;
10605                         }
10606
10607                         if (alloc == NULL) {
10608                                 /* Valuetype */
10609                                 EMIT_NEW_TEMPLOAD (cfg, ins, iargs [0]->inst_c0);
10610                                 type_to_eval_stack_type (cfg, &ins->klass->byval_arg, ins);
10611                                 *sp++= ins;
10612                         } else {
10613                                 *sp++ = alloc;
10614                         }
10615                         
10616                         ip += 5;
10617                         inline_costs += 5;
10618                         if (!(seq_point_locs && mono_bitset_test_fast (seq_point_locs, ip - header->code)))
10619                                 emit_seq_point (cfg, method, ip, FALSE, TRUE);
10620                         break;
10621                 }
10622                 case CEE_CASTCLASS:
10623                         CHECK_STACK (1);
10624                         --sp;
10625                         CHECK_OPSIZE (5);
10626                         token = read32 (ip + 1);
10627                         klass = mini_get_class (method, token, generic_context);
10628                         CHECK_TYPELOAD (klass);
10629                         if (sp [0]->type != STACK_OBJ)
10630                                 UNVERIFIED;
10631
10632                         ins = handle_castclass (cfg, klass, *sp, ip, &inline_costs);
10633                         CHECK_CFG_EXCEPTION;
10634
10635                         *sp ++ = ins;
10636                         ip += 5;
10637                         break;
10638                 case CEE_ISINST: {
10639                         CHECK_STACK (1);
10640                         --sp;
10641                         CHECK_OPSIZE (5);
10642                         token = read32 (ip + 1);
10643                         klass = mini_get_class (method, token, generic_context);
10644                         CHECK_TYPELOAD (klass);
10645                         if (sp [0]->type != STACK_OBJ)
10646                                 UNVERIFIED;
10647  
10648                         context_used = mini_class_check_context_used (cfg, klass);
10649
10650                         if (!context_used && mini_class_has_reference_variant_generic_argument (cfg, klass, context_used)) {
10651                                 MonoMethod *mono_isinst = mono_marshal_get_isinst_with_cache ();
10652                                 MonoInst *args [3];
10653                                 int idx;
10654
10655                                 /* obj */
10656                                 args [0] = *sp;
10657
10658                                 /* klass */
10659                                 EMIT_NEW_CLASSCONST (cfg, args [1], klass);
10660
10661                                 /* inline cache*/
10662                                 if (cfg->compile_aot) {
10663                                         idx = get_castclass_cache_idx (cfg);
10664                                         EMIT_NEW_AOTCONST (cfg, args [2], MONO_PATCH_INFO_CASTCLASS_CACHE, GINT_TO_POINTER (idx));
10665                                 } else {
10666                                         EMIT_NEW_PCONST (cfg, args [2], mono_domain_alloc0 (cfg->domain, sizeof (gpointer)));
10667                                 }
10668
10669                                 *sp++ = mono_emit_method_call (cfg, mono_isinst, args, NULL);
10670                                 ip += 5;
10671                                 inline_costs += 2;
10672                         } else if (!context_used && (mono_class_is_marshalbyref (klass) || klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
10673                                 MonoMethod *mono_isinst;
10674                                 MonoInst *iargs [1];
10675                                 int costs;
10676
10677                                 mono_isinst = mono_marshal_get_isinst (klass); 
10678                                 iargs [0] = sp [0];
10679
10680                                 costs = inline_method (cfg, mono_isinst, mono_method_signature (mono_isinst), 
10681                                                                            iargs, ip, cfg->real_offset, TRUE);
10682                                 CHECK_CFG_EXCEPTION;
10683                                 g_assert (costs > 0);
10684                                 
10685                                 ip += 5;
10686                                 cfg->real_offset += 5;
10687
10688                                 *sp++= iargs [0];
10689
10690                                 inline_costs += costs;
10691                         }
10692                         else {
10693                                 ins = handle_isinst (cfg, klass, *sp, context_used);
10694                                 CHECK_CFG_EXCEPTION;
10695                                 *sp ++ = ins;
10696                                 ip += 5;
10697                         }
10698                         break;
10699                 }
10700                 case CEE_UNBOX_ANY: {
10701                         MonoInst *res, *addr;
10702
10703                         CHECK_STACK (1);
10704                         --sp;
10705                         CHECK_OPSIZE (5);
10706                         token = read32 (ip + 1);
10707                         klass = mini_get_class (method, token, generic_context);
10708                         CHECK_TYPELOAD (klass);
10709
10710                         mono_save_token_info (cfg, image, token, klass);
10711
10712                         context_used = mini_class_check_context_used (cfg, klass);
10713
10714                         if (mini_is_gsharedvt_klass (klass)) {
10715                                 res = handle_unbox_gsharedvt (cfg, klass, *sp);
10716                                 inline_costs += 2;
10717                         } else if (generic_class_is_reference_type (cfg, klass)) {
10718                                 res = handle_castclass (cfg, klass, *sp, ip, &inline_costs);
10719                                 CHECK_CFG_EXCEPTION;
10720                         } else if (mono_class_is_nullable (klass)) {
10721                                 res = handle_unbox_nullable (cfg, *sp, klass, context_used);
10722                         } else {
10723                                 addr = handle_unbox (cfg, klass, sp, context_used);
10724                                 /* LDOBJ */
10725                                 EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, addr->dreg, 0);
10726                                 res = ins;
10727                                 inline_costs += 2;
10728                         }
10729
10730                         *sp ++ = res;
10731                         ip += 5;
10732                         break;
10733                 }
10734                 case CEE_BOX: {
10735                         MonoInst *val;
10736                         MonoClass *enum_class;
10737                         MonoMethod *has_flag;
10738
10739                         CHECK_STACK (1);
10740                         --sp;
10741                         val = *sp;
10742                         CHECK_OPSIZE (5);
10743                         token = read32 (ip + 1);
10744                         klass = mini_get_class (method, token, generic_context);
10745                         CHECK_TYPELOAD (klass);
10746
10747                         mono_save_token_info (cfg, image, token, klass);
10748
10749                         context_used = mini_class_check_context_used (cfg, klass);
10750
10751                         if (generic_class_is_reference_type (cfg, klass)) {
10752                                 *sp++ = val;
10753                                 ip += 5;
10754                                 break;
10755                         }
10756
10757                         if (klass == mono_defaults.void_class)
10758                                 UNVERIFIED;
10759                         if (target_type_is_incompatible (cfg, &klass->byval_arg, *sp))
10760                                 UNVERIFIED;
10761                         /* frequent check in generic code: box (struct), brtrue */
10762
10763                         /*
10764                          * Look for:
10765                          *
10766                          *   <push int/long ptr>
10767                          *   <push int/long>
10768                          *   box MyFlags
10769                          *   constrained. MyFlags
10770                          *   callvirt instace bool class [mscorlib] System.Enum::HasFlag (class [mscorlib] System.Enum)
10771                          *
10772                          * If we find this sequence and the operand types on box and constrained
10773                          * are equal, we can emit a specialized instruction sequence instead of
10774                          * the very slow HasFlag () call.
10775                          */
10776                         if ((cfg->opt & MONO_OPT_INTRINS) &&
10777                             /* Cheap checks first. */
10778                             ip + 5 + 6 + 5 < end &&
10779                             ip [5] == CEE_PREFIX1 &&
10780                             ip [6] == CEE_CONSTRAINED_ &&
10781                             ip [11] == CEE_CALLVIRT &&
10782                             ip_in_bb (cfg, cfg->cbb, ip + 5 + 6 + 5) &&
10783                             mono_class_is_enum (klass) &&
10784                             (enum_class = mini_get_class (method, read32 (ip + 7), generic_context)) &&
10785                             (has_flag = mini_get_method (cfg, method, read32 (ip + 12), NULL, generic_context)) &&
10786                             has_flag->klass == mono_defaults.enum_class &&
10787                             !strcmp (has_flag->name, "HasFlag") &&
10788                             has_flag->signature->hasthis &&
10789                             has_flag->signature->param_count == 1) {
10790                                 CHECK_TYPELOAD (enum_class);
10791
10792                                 if (enum_class == klass) {
10793                                         MonoInst *enum_this, *enum_flag;
10794
10795                                         ip += 5 + 6 + 5;
10796                                         --sp;
10797
10798                                         enum_this = sp [0];
10799                                         enum_flag = sp [1];
10800
10801                                         *sp++ = handle_enum_has_flag (cfg, klass, enum_this, enum_flag);
10802                                         break;
10803                                 }
10804                         }
10805
10806                         // FIXME: LLVM can't handle the inconsistent bb linking
10807                         if (!mono_class_is_nullable (klass) &&
10808                                 !mini_is_gsharedvt_klass (klass) &&
10809                                 ip + 5 < end && ip_in_bb (cfg, cfg->cbb, ip + 5) &&
10810                                 (ip [5] == CEE_BRTRUE || 
10811                                  ip [5] == CEE_BRTRUE_S ||
10812                                  ip [5] == CEE_BRFALSE ||
10813                                  ip [5] == CEE_BRFALSE_S)) {
10814                                 gboolean is_true = ip [5] == CEE_BRTRUE || ip [5] == CEE_BRTRUE_S;
10815                                 int dreg;
10816                                 MonoBasicBlock *true_bb, *false_bb;
10817
10818                                 ip += 5;
10819
10820                                 if (cfg->verbose_level > 3) {
10821                                         printf ("converting (in B%d: stack: %d) %s", cfg->cbb->block_num, (int)(sp - stack_start), mono_disasm_code_one (NULL, method, ip, NULL));
10822                                         printf ("<box+brtrue opt>\n");
10823                                 }
10824
10825                                 switch (*ip) {
10826                                 case CEE_BRTRUE_S:
10827                                 case CEE_BRFALSE_S:
10828                                         CHECK_OPSIZE (2);
10829                                         ip++;
10830                                         target = ip + 1 + (signed char)(*ip);
10831                                         ip++;
10832                                         break;
10833                                 case CEE_BRTRUE:
10834                                 case CEE_BRFALSE:
10835                                         CHECK_OPSIZE (5);
10836                                         ip++;
10837                                         target = ip + 4 + (gint)(read32 (ip));
10838                                         ip += 4;
10839                                         break;
10840                                 default:
10841                                         g_assert_not_reached ();
10842                                 }
10843
10844                                 /* 
10845                                  * We need to link both bblocks, since it is needed for handling stack
10846                                  * arguments correctly (See test_0_box_brtrue_opt_regress_81102).
10847                                  * Branching to only one of them would lead to inconsistencies, so
10848                                  * generate an ICONST+BRTRUE, the branch opts will get rid of them.
10849                                  */
10850                                 GET_BBLOCK (cfg, true_bb, target);
10851                                 GET_BBLOCK (cfg, false_bb, ip);
10852
10853                                 mono_link_bblock (cfg, cfg->cbb, true_bb);
10854                                 mono_link_bblock (cfg, cfg->cbb, false_bb);
10855
10856                                 if (sp != stack_start) {
10857                                         handle_stack_args (cfg, stack_start, sp - stack_start);
10858                                         sp = stack_start;
10859                                         CHECK_UNVERIFIABLE (cfg);
10860                                 }
10861
10862                                 if (COMPILE_LLVM (cfg)) {
10863                                         dreg = alloc_ireg (cfg);
10864                                         MONO_EMIT_NEW_ICONST (cfg, dreg, 0);
10865                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, dreg, is_true ? 0 : 1);
10866
10867                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, OP_IBEQ, true_bb, false_bb);
10868                                 } else {
10869                                         /* The JIT can't eliminate the iconst+compare */
10870                                         MONO_INST_NEW (cfg, ins, OP_BR);
10871                                         ins->inst_target_bb = is_true ? true_bb : false_bb;
10872                                         MONO_ADD_INS (cfg->cbb, ins);
10873                                 }
10874
10875                                 start_new_bblock = 1;
10876                                 break;
10877                         }
10878
10879                         *sp++ = handle_box (cfg, val, klass, context_used);
10880
10881                         CHECK_CFG_EXCEPTION;
10882                         ip += 5;
10883                         inline_costs += 1;
10884                         break;
10885                 }
10886                 case CEE_UNBOX: {
10887                         CHECK_STACK (1);
10888                         --sp;
10889                         CHECK_OPSIZE (5);
10890                         token = read32 (ip + 1);
10891                         klass = mini_get_class (method, token, generic_context);
10892                         CHECK_TYPELOAD (klass);
10893
10894                         mono_save_token_info (cfg, image, token, klass);
10895
10896                         context_used = mini_class_check_context_used (cfg, klass);
10897
10898                         if (mono_class_is_nullable (klass)) {
10899                                 MonoInst *val;
10900
10901                                 val = handle_unbox_nullable (cfg, *sp, klass, context_used);
10902                                 EMIT_NEW_VARLOADA (cfg, ins, get_vreg_to_inst (cfg, val->dreg), &val->klass->byval_arg);
10903
10904                                 *sp++= ins;
10905                         } else {
10906                                 ins = handle_unbox (cfg, klass, sp, context_used);
10907                                 *sp++ = ins;
10908                         }
10909                         ip += 5;
10910                         inline_costs += 2;
10911                         break;
10912                 }
10913                 case CEE_LDFLD:
10914                 case CEE_LDFLDA:
10915                 case CEE_STFLD:
10916                 case CEE_LDSFLD:
10917                 case CEE_LDSFLDA:
10918                 case CEE_STSFLD: {
10919                         MonoClassField *field;
10920 #ifndef DISABLE_REMOTING
10921                         int costs;
10922 #endif
10923                         guint foffset;
10924                         gboolean is_instance;
10925                         int op;
10926                         gpointer addr = NULL;
10927                         gboolean is_special_static;
10928                         MonoType *ftype;
10929                         MonoInst *store_val = NULL;
10930                         MonoInst *thread_ins;
10931
10932                         op = *ip;
10933                         is_instance = (op == CEE_LDFLD || op == CEE_LDFLDA || op == CEE_STFLD);
10934                         if (is_instance) {
10935                                 if (op == CEE_STFLD) {
10936                                         CHECK_STACK (2);
10937                                         sp -= 2;
10938                                         store_val = sp [1];
10939                                 } else {
10940                                         CHECK_STACK (1);
10941                                         --sp;
10942                                 }
10943                                 if (sp [0]->type == STACK_I4 || sp [0]->type == STACK_I8 || sp [0]->type == STACK_R8)
10944                                         UNVERIFIED;
10945                                 if (*ip != CEE_LDFLD && sp [0]->type == STACK_VTYPE)
10946                                         UNVERIFIED;
10947                         } else {
10948                                 if (op == CEE_STSFLD) {
10949                                         CHECK_STACK (1);
10950                                         sp--;
10951                                         store_val = sp [0];
10952                                 }
10953                         }
10954
10955                         CHECK_OPSIZE (5);
10956                         token = read32 (ip + 1);
10957                         if (method->wrapper_type != MONO_WRAPPER_NONE) {
10958                                 field = mono_method_get_wrapper_data (method, token);
10959                                 klass = field->parent;
10960                         }
10961                         else {
10962                                 field = mono_field_from_token_checked (image, token, &klass, generic_context, &cfg->error);
10963                                 CHECK_CFG_ERROR;
10964                         }
10965                         if (!dont_verify && !cfg->skip_visibility && !mono_method_can_access_field (method, field))
10966                                 FIELD_ACCESS_FAILURE (method, field);
10967                         mono_class_init (klass);
10968
10969                         /* if the class is Critical then transparent code cannot access it's fields */
10970                         if (!is_instance && mono_security_core_clr_enabled ())
10971                                 ensure_method_is_allowed_to_access_field (cfg, method, field);
10972
10973                         /* XXX this is technically required but, so far (SL2), no [SecurityCritical] types (not many exists) have
10974                            any visible *instance* field  (in fact there's a single case for a static field in Marshal) XXX
10975                         if (mono_security_core_clr_enabled ())
10976                                 ensure_method_is_allowed_to_access_field (cfg, method, field);
10977                         */
10978
10979                         ftype = mono_field_get_type (field);
10980
10981                         /*
10982                          * LDFLD etc. is usable on static fields as well, so convert those cases to
10983                          * the static case.
10984                          */
10985                         if (is_instance && ftype->attrs & FIELD_ATTRIBUTE_STATIC) {
10986                                 switch (op) {
10987                                 case CEE_LDFLD:
10988                                         op = CEE_LDSFLD;
10989                                         break;
10990                                 case CEE_STFLD:
10991                                         op = CEE_STSFLD;
10992                                         break;
10993                                 case CEE_LDFLDA:
10994                                         op = CEE_LDSFLDA;
10995                                         break;
10996                                 default:
10997                                         g_assert_not_reached ();
10998                                 }
10999                                 is_instance = FALSE;
11000                         }
11001
11002                         context_used = mini_class_check_context_used (cfg, klass);
11003
11004                         /* INSTANCE CASE */
11005
11006                         foffset = klass->valuetype? field->offset - sizeof (MonoObject): field->offset;
11007                         if (op == CEE_STFLD) {
11008                                 if (target_type_is_incompatible (cfg, field->type, sp [1]))
11009                                         UNVERIFIED;
11010 #ifndef DISABLE_REMOTING
11011                                 if ((mono_class_is_marshalbyref (klass) && !MONO_CHECK_THIS (sp [0])) || mono_class_is_contextbound (klass) || klass == mono_defaults.marshalbyrefobject_class) {
11012                                         MonoMethod *stfld_wrapper = mono_marshal_get_stfld_wrapper (field->type); 
11013                                         MonoInst *iargs [5];
11014
11015                                         GSHAREDVT_FAILURE (op);
11016
11017                                         iargs [0] = sp [0];
11018                                         EMIT_NEW_CLASSCONST (cfg, iargs [1], klass);
11019                                         EMIT_NEW_FIELDCONST (cfg, iargs [2], field);
11020                                         EMIT_NEW_ICONST (cfg, iargs [3], klass->valuetype ? field->offset - sizeof (MonoObject) : 
11021                                                     field->offset);
11022                                         iargs [4] = sp [1];
11023
11024                                         if (cfg->opt & MONO_OPT_INLINE || cfg->compile_aot) {
11025                                                 costs = inline_method (cfg, stfld_wrapper, mono_method_signature (stfld_wrapper), 
11026                                                                                            iargs, ip, cfg->real_offset, TRUE);
11027                                                 CHECK_CFG_EXCEPTION;
11028                                                 g_assert (costs > 0);
11029                                                       
11030                                                 cfg->real_offset += 5;
11031
11032                                                 inline_costs += costs;
11033                                         } else {
11034                                                 mono_emit_method_call (cfg, stfld_wrapper, iargs, NULL);
11035                                         }
11036                                 } else
11037 #endif
11038                                 {
11039                                         MonoInst *store;
11040
11041                                         MONO_EMIT_NULL_CHECK (cfg, sp [0]->dreg);
11042
11043                                         if (mini_is_gsharedvt_klass (klass)) {
11044                                                 MonoInst *offset_ins;
11045
11046                                                 context_used = mini_class_check_context_used (cfg, klass);
11047
11048                                                 offset_ins = emit_get_gsharedvt_info (cfg, field, MONO_RGCTX_INFO_FIELD_OFFSET);
11049                                                 dreg = alloc_ireg_mp (cfg);
11050                                                 EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, sp [0]->dreg, offset_ins->dreg);
11051                                                 /* The decomposition will call mini_emit_stobj () which will emit a wbarrier if needed */
11052                                                 EMIT_NEW_STORE_MEMBASE_TYPE (cfg, store, field->type, dreg, 0, sp [1]->dreg);
11053                                         } else {
11054                                                 EMIT_NEW_STORE_MEMBASE_TYPE (cfg, store, field->type, sp [0]->dreg, foffset, sp [1]->dreg);
11055                                         }
11056                                         if (sp [0]->opcode != OP_LDADDR)
11057                                                 store->flags |= MONO_INST_FAULT;
11058
11059                                 if (cfg->gen_write_barriers && mini_type_to_stind (cfg, field->type) == CEE_STIND_REF && !(sp [1]->opcode == OP_PCONST && sp [1]->inst_c0 == 0)) {
11060                                         /* insert call to write barrier */
11061                                         MonoInst *ptr;
11062                                         int dreg;
11063
11064                                         dreg = alloc_ireg_mp (cfg);
11065                                         EMIT_NEW_BIALU_IMM (cfg, ptr, OP_PADD_IMM, dreg, sp [0]->dreg, foffset);
11066                                         emit_write_barrier (cfg, ptr, sp [1]);
11067                                 }
11068
11069                                         store->flags |= ins_flag;
11070                                 }
11071                                 ins_flag = 0;
11072                                 ip += 5;
11073                                 break;
11074                         }
11075
11076 #ifndef DISABLE_REMOTING
11077                         if (is_instance && ((mono_class_is_marshalbyref (klass) && !MONO_CHECK_THIS (sp [0])) || mono_class_is_contextbound (klass) || klass == mono_defaults.marshalbyrefobject_class)) {
11078                                 MonoMethod *wrapper = (op == CEE_LDFLDA) ? mono_marshal_get_ldflda_wrapper (field->type) : mono_marshal_get_ldfld_wrapper (field->type); 
11079                                 MonoInst *iargs [4];
11080
11081                                 GSHAREDVT_FAILURE (op);
11082
11083                                 iargs [0] = sp [0];
11084                                 EMIT_NEW_CLASSCONST (cfg, iargs [1], klass);
11085                                 EMIT_NEW_FIELDCONST (cfg, iargs [2], field);
11086                                 EMIT_NEW_ICONST (cfg, iargs [3], klass->valuetype ? field->offset - sizeof (MonoObject) : field->offset);
11087                                 if (cfg->opt & MONO_OPT_INLINE || cfg->compile_aot) {
11088                                         costs = inline_method (cfg, wrapper, mono_method_signature (wrapper), 
11089                                                                                    iargs, ip, cfg->real_offset, TRUE);
11090                                         CHECK_CFG_EXCEPTION;
11091                                         g_assert (costs > 0);
11092                                                       
11093                                         cfg->real_offset += 5;
11094
11095                                         *sp++ = iargs [0];
11096
11097                                         inline_costs += costs;
11098                                 } else {
11099                                         ins = mono_emit_method_call (cfg, wrapper, iargs, NULL);
11100                                         *sp++ = ins;
11101                                 }
11102                         } else 
11103 #endif
11104                         if (is_instance) {
11105                                 if (sp [0]->type == STACK_VTYPE) {
11106                                         MonoInst *var;
11107
11108                                         /* Have to compute the address of the variable */
11109
11110                                         var = get_vreg_to_inst (cfg, sp [0]->dreg);
11111                                         if (!var)
11112                                                 var = mono_compile_create_var_for_vreg (cfg, &klass->byval_arg, OP_LOCAL, sp [0]->dreg);
11113                                         else
11114                                                 g_assert (var->klass == klass);
11115                                         
11116                                         EMIT_NEW_VARLOADA (cfg, ins, var, &var->klass->byval_arg);
11117                                         sp [0] = ins;
11118                                 }
11119
11120                                 if (op == CEE_LDFLDA) {
11121                                         if (sp [0]->type == STACK_OBJ) {
11122                                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, sp [0]->dreg, 0);
11123                                                 MONO_EMIT_NEW_COND_EXC (cfg, EQ, "NullReferenceException");
11124                                         }
11125
11126                                         dreg = alloc_ireg_mp (cfg);
11127
11128                                         if (mini_is_gsharedvt_klass (klass)) {
11129                                                 MonoInst *offset_ins;
11130
11131                                                 offset_ins = emit_get_gsharedvt_info (cfg, field, MONO_RGCTX_INFO_FIELD_OFFSET);
11132                                                 EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, sp [0]->dreg, offset_ins->dreg);
11133                                         } else {
11134                                                 EMIT_NEW_BIALU_IMM (cfg, ins, OP_PADD_IMM, dreg, sp [0]->dreg, foffset);
11135                                         }
11136                                         ins->klass = mono_class_from_mono_type (field->type);
11137                                         ins->type = STACK_MP;
11138                                         *sp++ = ins;
11139                                 } else {
11140                                         MonoInst *load;
11141
11142                                         MONO_EMIT_NULL_CHECK (cfg, sp [0]->dreg);
11143
11144                                         if (mini_is_gsharedvt_klass (klass)) {
11145                                                 MonoInst *offset_ins;
11146
11147                                                 offset_ins = emit_get_gsharedvt_info (cfg, field, MONO_RGCTX_INFO_FIELD_OFFSET);
11148                                                 dreg = alloc_ireg_mp (cfg);
11149                                                 EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, sp [0]->dreg, offset_ins->dreg);
11150                                                 EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, load, field->type, dreg, 0);
11151                                         } else {
11152                                                 EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, load, field->type, sp [0]->dreg, foffset);
11153                                         }
11154                                         load->flags |= ins_flag;
11155                                         if (sp [0]->opcode != OP_LDADDR)
11156                                                 load->flags |= MONO_INST_FAULT;
11157                                         *sp++ = load;
11158                                 }
11159                         }
11160
11161                         if (is_instance) {
11162                                 ins_flag = 0;
11163                                 ip += 5;
11164                                 break;
11165                         }
11166
11167                         /* STATIC CASE */
11168                         context_used = mini_class_check_context_used (cfg, klass);
11169
11170                         if (ftype->attrs & FIELD_ATTRIBUTE_LITERAL)
11171                                 UNVERIFIED;
11172
11173                         /* The special_static_fields field is init'd in mono_class_vtable, so it needs
11174                          * to be called here.
11175                          */
11176                         if (!context_used && !(cfg->opt & MONO_OPT_SHARED)) {
11177                                 mono_class_vtable (cfg->domain, klass);
11178                                 CHECK_TYPELOAD (klass);
11179                         }
11180                         mono_domain_lock (cfg->domain);
11181                         if (cfg->domain->special_static_fields)
11182                                 addr = g_hash_table_lookup (cfg->domain->special_static_fields, field);
11183                         mono_domain_unlock (cfg->domain);
11184
11185                         is_special_static = mono_class_field_is_special_static (field);
11186
11187                         if (is_special_static && ((gsize)addr & 0x80000000) == 0)
11188                                 thread_ins = mono_get_thread_intrinsic (cfg);
11189                         else
11190                                 thread_ins = NULL;
11191
11192                         /* Generate IR to compute the field address */
11193                         if (is_special_static && ((gsize)addr & 0x80000000) == 0 && thread_ins && !(cfg->opt & MONO_OPT_SHARED) && !context_used) {
11194                                 /*
11195                                  * Fast access to TLS data
11196                                  * Inline version of get_thread_static_data () in
11197                                  * threads.c.
11198                                  */
11199                                 guint32 offset;
11200                                 int idx, static_data_reg, array_reg, dreg;
11201
11202                                 GSHAREDVT_FAILURE (op);
11203
11204                                 MONO_ADD_INS (cfg->cbb, thread_ins);
11205                                 static_data_reg = alloc_ireg (cfg);
11206                                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, static_data_reg, thread_ins->dreg, MONO_STRUCT_OFFSET (MonoInternalThread, static_data));
11207
11208                                 if (cfg->compile_aot) {
11209                                         int offset_reg, offset2_reg, idx_reg;
11210
11211                                         /* For TLS variables, this will return the TLS offset */
11212                                         EMIT_NEW_SFLDACONST (cfg, ins, field);
11213                                         offset_reg = ins->dreg;
11214                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, offset_reg, offset_reg, 0x7fffffff);
11215                                         idx_reg = alloc_ireg (cfg);
11216                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, idx_reg, offset_reg, 0x3f);
11217                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHL_IMM, idx_reg, idx_reg, sizeof (gpointer) == 8 ? 3 : 2);
11218                                         MONO_EMIT_NEW_BIALU (cfg, OP_PADD, static_data_reg, static_data_reg, idx_reg);
11219                                         array_reg = alloc_ireg (cfg);
11220                                         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, array_reg, static_data_reg, 0);
11221                                         offset2_reg = alloc_ireg (cfg);
11222                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_UN_IMM, offset2_reg, offset_reg, 6);
11223                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, offset2_reg, offset2_reg, 0x1ffffff);
11224                                         dreg = alloc_ireg (cfg);
11225                                         EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, array_reg, offset2_reg);
11226                                 } else {
11227                                         offset = (gsize)addr & 0x7fffffff;
11228                                         idx = offset & 0x3f;
11229
11230                                         array_reg = alloc_ireg (cfg);
11231                                         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, array_reg, static_data_reg, idx * sizeof (gpointer));
11232                                         dreg = alloc_ireg (cfg);
11233                                         EMIT_NEW_BIALU_IMM (cfg, ins, OP_ADD_IMM, dreg, array_reg, ((offset >> 6) & 0x1ffffff));
11234                                 }
11235                         } else if ((cfg->opt & MONO_OPT_SHARED) ||
11236                                         (cfg->compile_aot && is_special_static) ||
11237                                         (context_used && is_special_static)) {
11238                                 MonoInst *iargs [2];
11239
11240                                 g_assert (field->parent);
11241                                 EMIT_NEW_DOMAINCONST (cfg, iargs [0]);
11242                                 if (context_used) {
11243                                         iargs [1] = emit_get_rgctx_field (cfg, context_used,
11244                                                 field, MONO_RGCTX_INFO_CLASS_FIELD);
11245                                 } else {
11246                                         EMIT_NEW_FIELDCONST (cfg, iargs [1], field);
11247                                 }
11248                                 ins = mono_emit_jit_icall (cfg, mono_class_static_field_address, iargs);
11249                         } else if (context_used) {
11250                                 MonoInst *static_data;
11251
11252                                 /*
11253                                 g_print ("sharing static field access in %s.%s.%s - depth %d offset %d\n",
11254                                         method->klass->name_space, method->klass->name, method->name,
11255                                         depth, field->offset);
11256                                 */
11257
11258                                 if (mono_class_needs_cctor_run (klass, method))
11259                                         emit_class_init (cfg, klass);
11260
11261                                 /*
11262                                  * The pointer we're computing here is
11263                                  *
11264                                  *   super_info.static_data + field->offset
11265                                  */
11266                                 static_data = emit_get_rgctx_klass (cfg, context_used,
11267                                         klass, MONO_RGCTX_INFO_STATIC_DATA);
11268
11269                                 if (mini_is_gsharedvt_klass (klass)) {
11270                                         MonoInst *offset_ins;
11271
11272                                         offset_ins = emit_get_rgctx_field (cfg, context_used, field, MONO_RGCTX_INFO_FIELD_OFFSET);
11273                                         dreg = alloc_ireg_mp (cfg);
11274                                         EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, static_data->dreg, offset_ins->dreg);
11275                                 } else if (field->offset == 0) {
11276                                         ins = static_data;
11277                                 } else {
11278                                         int addr_reg = mono_alloc_preg (cfg);
11279                                         EMIT_NEW_BIALU_IMM (cfg, ins, OP_PADD_IMM, addr_reg, static_data->dreg, field->offset);
11280                                 }
11281                                 } else if ((cfg->opt & MONO_OPT_SHARED) || (cfg->compile_aot && addr)) {
11282                                 MonoInst *iargs [2];
11283
11284                                 g_assert (field->parent);
11285                                 EMIT_NEW_DOMAINCONST (cfg, iargs [0]);
11286                                 EMIT_NEW_FIELDCONST (cfg, iargs [1], field);
11287                                 ins = mono_emit_jit_icall (cfg, mono_class_static_field_address, iargs);
11288                         } else {
11289                                 MonoVTable *vtable = NULL;
11290
11291                                 if (!cfg->compile_aot)
11292                                         vtable = mono_class_vtable (cfg->domain, klass);
11293                                 CHECK_TYPELOAD (klass);
11294
11295                                 if (!addr) {
11296                                         if (mini_field_access_needs_cctor_run (cfg, method, klass, vtable)) {
11297                                                 if (!(g_slist_find (class_inits, klass))) {
11298                                                         emit_class_init (cfg, klass);
11299                                                         if (cfg->verbose_level > 2)
11300                                                                 printf ("class %s.%s needs init call for %s\n", klass->name_space, klass->name, mono_field_get_name (field));
11301                                                         class_inits = g_slist_prepend (class_inits, klass);
11302                                                 }
11303                                         } else {
11304                                                 if (cfg->run_cctors) {
11305                                                         MonoException *ex;
11306                                                         /* This makes so that inline cannot trigger */
11307                                                         /* .cctors: too many apps depend on them */
11308                                                         /* running with a specific order... */
11309                                                         g_assert (vtable);
11310                                                         if (! vtable->initialized)
11311                                                                 INLINE_FAILURE ("class init");
11312                                                         ex = mono_runtime_class_init_full (vtable, FALSE);
11313                                                         if (ex) {
11314                                                                 set_exception_object (cfg, ex);
11315                                                                 goto exception_exit;
11316                                                         }
11317                                                 }
11318                                         }
11319                                         if (cfg->compile_aot)
11320                                                 EMIT_NEW_SFLDACONST (cfg, ins, field);
11321                                         else {
11322                                                 g_assert (vtable);
11323                                                 addr = (char*)mono_vtable_get_static_field_data (vtable) + field->offset;
11324                                                 g_assert (addr);
11325                                                 EMIT_NEW_PCONST (cfg, ins, addr);
11326                                         }
11327                                 } else {
11328                                         MonoInst *iargs [1];
11329                                         EMIT_NEW_ICONST (cfg, iargs [0], GPOINTER_TO_UINT (addr));
11330                                         ins = mono_emit_jit_icall (cfg, mono_get_special_static_data, iargs);
11331                                 }
11332                         }
11333
11334                         /* Generate IR to do the actual load/store operation */
11335
11336                         if ((op == CEE_STFLD || op == CEE_STSFLD) && (ins_flag & MONO_INST_VOLATILE)) {
11337                                 /* Volatile stores have release semantics, see 12.6.7 in Ecma 335 */
11338                                 emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL);
11339                         }
11340
11341                         if (op == CEE_LDSFLDA) {
11342                                 ins->klass = mono_class_from_mono_type (ftype);
11343                                 ins->type = STACK_PTR;
11344                                 *sp++ = ins;
11345                         } else if (op == CEE_STSFLD) {
11346                                 MonoInst *store;
11347
11348                                 EMIT_NEW_STORE_MEMBASE_TYPE (cfg, store, ftype, ins->dreg, 0, store_val->dreg);
11349                                 store->flags |= ins_flag;
11350                         } else {
11351                                 gboolean is_const = FALSE;
11352                                 MonoVTable *vtable = NULL;
11353                                 gpointer addr = NULL;
11354
11355                                 if (!context_used) {
11356                                         vtable = mono_class_vtable (cfg->domain, klass);
11357                                         CHECK_TYPELOAD (klass);
11358                                 }
11359                                 if ((ftype->attrs & FIELD_ATTRIBUTE_INIT_ONLY) && (((addr = mono_aot_readonly_field_override (field)) != NULL) ||
11360                                                 (!context_used && !((cfg->opt & MONO_OPT_SHARED) || cfg->compile_aot) && vtable->initialized))) {
11361                                         int ro_type = ftype->type;
11362                                         if (!addr)
11363                                                 addr = (char*)mono_vtable_get_static_field_data (vtable) + field->offset;
11364                                         if (ro_type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
11365                                                 ro_type = mono_class_enum_basetype (ftype->data.klass)->type;
11366                                         }
11367
11368                                         GSHAREDVT_FAILURE (op);
11369
11370                                         /* printf ("RO-FIELD %s.%s:%s\n", klass->name_space, klass->name, mono_field_get_name (field));*/
11371                                         is_const = TRUE;
11372                                         switch (ro_type) {
11373                                         case MONO_TYPE_BOOLEAN:
11374                                         case MONO_TYPE_U1:
11375                                                 EMIT_NEW_ICONST (cfg, *sp, *((guint8 *)addr));
11376                                                 sp++;
11377                                                 break;
11378                                         case MONO_TYPE_I1:
11379                                                 EMIT_NEW_ICONST (cfg, *sp, *((gint8 *)addr));
11380                                                 sp++;
11381                                                 break;                                          
11382                                         case MONO_TYPE_CHAR:
11383                                         case MONO_TYPE_U2:
11384                                                 EMIT_NEW_ICONST (cfg, *sp, *((guint16 *)addr));
11385                                                 sp++;
11386                                                 break;
11387                                         case MONO_TYPE_I2:
11388                                                 EMIT_NEW_ICONST (cfg, *sp, *((gint16 *)addr));
11389                                                 sp++;
11390                                                 break;
11391                                                 break;
11392                                         case MONO_TYPE_I4:
11393                                                 EMIT_NEW_ICONST (cfg, *sp, *((gint32 *)addr));
11394                                                 sp++;
11395                                                 break;                                          
11396                                         case MONO_TYPE_U4:
11397                                                 EMIT_NEW_ICONST (cfg, *sp, *((guint32 *)addr));
11398                                                 sp++;
11399                                                 break;
11400                                         case MONO_TYPE_I:
11401                                         case MONO_TYPE_U:
11402                                         case MONO_TYPE_PTR:
11403                                         case MONO_TYPE_FNPTR:
11404                                                 EMIT_NEW_PCONST (cfg, *sp, *((gpointer *)addr));
11405                                                 type_to_eval_stack_type ((cfg), field->type, *sp);
11406                                                 sp++;
11407                                                 break;
11408                                         case MONO_TYPE_STRING:
11409                                         case MONO_TYPE_OBJECT:
11410                                         case MONO_TYPE_CLASS:
11411                                         case MONO_TYPE_SZARRAY:
11412                                         case MONO_TYPE_ARRAY:
11413                                                 if (!mono_gc_is_moving ()) {
11414                                                         EMIT_NEW_PCONST (cfg, *sp, *((gpointer *)addr));
11415                                                         type_to_eval_stack_type ((cfg), field->type, *sp);
11416                                                         sp++;
11417                                                 } else {
11418                                                         is_const = FALSE;
11419                                                 }
11420                                                 break;
11421                                         case MONO_TYPE_I8:
11422                                         case MONO_TYPE_U8:
11423                                                 EMIT_NEW_I8CONST (cfg, *sp, *((gint64 *)addr));
11424                                                 sp++;
11425                                                 break;
11426                                         case MONO_TYPE_R4:
11427                                         case MONO_TYPE_R8:
11428                                         case MONO_TYPE_VALUETYPE:
11429                                         default:
11430                                                 is_const = FALSE;
11431                                                 break;
11432                                         }
11433                                 }
11434
11435                                 if (!is_const) {
11436                                         MonoInst *load;
11437
11438                                         CHECK_STACK_OVF (1);
11439
11440                                         EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, load, field->type, ins->dreg, 0);
11441                                         load->flags |= ins_flag;
11442                                         ins_flag = 0;
11443                                         *sp++ = load;
11444                                 }
11445                         }
11446
11447                         if ((op == CEE_LDFLD || op == CEE_LDSFLD) && (ins_flag & MONO_INST_VOLATILE)) {
11448                                 /* Volatile loads have acquire semantics, see 12.6.7 in Ecma 335 */
11449                                 emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_ACQ);
11450                         }
11451
11452                         ins_flag = 0;
11453                         ip += 5;
11454                         break;
11455                 }
11456                 case CEE_STOBJ:
11457                         CHECK_STACK (2);
11458                         sp -= 2;
11459                         CHECK_OPSIZE (5);
11460                         token = read32 (ip + 1);
11461                         klass = mini_get_class (method, token, generic_context);
11462                         CHECK_TYPELOAD (klass);
11463                         if (ins_flag & MONO_INST_VOLATILE) {
11464                                 /* Volatile stores have release semantics, see 12.6.7 in Ecma 335 */
11465                                 emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL);
11466                         }
11467                         /* FIXME: should check item at sp [1] is compatible with the type of the store. */
11468                         EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, sp [0]->dreg, 0, sp [1]->dreg);
11469                         ins->flags |= ins_flag;
11470                         if (cfg->gen_write_barriers && cfg->method->wrapper_type != MONO_WRAPPER_WRITE_BARRIER &&
11471                                         generic_class_is_reference_type (cfg, klass)) {
11472                                 /* insert call to write barrier */
11473                                 emit_write_barrier (cfg, sp [0], sp [1]);
11474                         }
11475                         ins_flag = 0;
11476                         ip += 5;
11477                         inline_costs += 1;
11478                         break;
11479
11480                         /*
11481                          * Array opcodes
11482                          */
11483                 case CEE_NEWARR: {
11484                         MonoInst *len_ins;
11485                         const char *data_ptr;
11486                         int data_size = 0;
11487                         guint32 field_token;
11488
11489                         CHECK_STACK (1);
11490                         --sp;
11491
11492                         CHECK_OPSIZE (5);
11493                         token = read32 (ip + 1);
11494
11495                         klass = mini_get_class (method, token, generic_context);
11496                         CHECK_TYPELOAD (klass);
11497
11498                         context_used = mini_class_check_context_used (cfg, klass);
11499
11500                         if (sp [0]->type == STACK_I8 || (SIZEOF_VOID_P == 8 && sp [0]->type == STACK_PTR)) {
11501                                 MONO_INST_NEW (cfg, ins, OP_LCONV_TO_OVF_U4);
11502                                 ins->sreg1 = sp [0]->dreg;
11503                                 ins->type = STACK_I4;
11504                                 ins->dreg = alloc_ireg (cfg);
11505                                 MONO_ADD_INS (cfg->cbb, ins);
11506                                 *sp = mono_decompose_opcode (cfg, ins);
11507                         }
11508
11509                         if (context_used) {
11510                                 MonoInst *args [3];
11511                                 MonoClass *array_class = mono_array_class_get (klass, 1);
11512                                 MonoMethod *managed_alloc = mono_gc_get_managed_array_allocator (array_class);
11513
11514                                 /* FIXME: Use OP_NEWARR and decompose later to help abcrem */
11515
11516                                 /* vtable */
11517                                 args [0] = emit_get_rgctx_klass (cfg, context_used,
11518                                         array_class, MONO_RGCTX_INFO_VTABLE);
11519                                 /* array len */
11520                                 args [1] = sp [0];
11521
11522                                 if (managed_alloc)
11523                                         ins = mono_emit_method_call (cfg, managed_alloc, args, NULL);
11524                                 else
11525                                         ins = mono_emit_jit_icall (cfg, mono_array_new_specific, args);
11526                         } else {
11527                                 if (cfg->opt & MONO_OPT_SHARED) {
11528                                         /* Decompose now to avoid problems with references to the domainvar */
11529                                         MonoInst *iargs [3];
11530
11531                                         EMIT_NEW_DOMAINCONST (cfg, iargs [0]);
11532                                         EMIT_NEW_CLASSCONST (cfg, iargs [1], klass);
11533                                         iargs [2] = sp [0];
11534
11535                                         ins = mono_emit_jit_icall (cfg, mono_array_new, iargs);
11536                                 } else {
11537                                         /* Decompose later since it is needed by abcrem */
11538                                         MonoClass *array_type = mono_array_class_get (klass, 1);
11539                                         mono_class_vtable (cfg->domain, array_type);
11540                                         CHECK_TYPELOAD (array_type);
11541
11542                                         MONO_INST_NEW (cfg, ins, OP_NEWARR);
11543                                         ins->dreg = alloc_ireg_ref (cfg);
11544                                         ins->sreg1 = sp [0]->dreg;
11545                                         ins->inst_newa_class = klass;
11546                                         ins->type = STACK_OBJ;
11547                                         ins->klass = array_type;
11548                                         MONO_ADD_INS (cfg->cbb, ins);
11549                                         cfg->flags |= MONO_CFG_HAS_ARRAY_ACCESS;
11550                                         cfg->cbb->has_array_access = TRUE;
11551
11552                                         /* Needed so mono_emit_load_get_addr () gets called */
11553                                         mono_get_got_var (cfg);
11554                                 }
11555                         }
11556
11557                         len_ins = sp [0];
11558                         ip += 5;
11559                         *sp++ = ins;
11560                         inline_costs += 1;
11561
11562                         /* 
11563                          * we inline/optimize the initialization sequence if possible.
11564                          * we should also allocate the array as not cleared, since we spend as much time clearing to 0 as initializing
11565                          * for small sizes open code the memcpy
11566                          * ensure the rva field is big enough
11567                          */
11568                         if ((cfg->opt & MONO_OPT_INTRINS) && ip + 6 < end && ip_in_bb (cfg, cfg->cbb, ip + 6) && (len_ins->opcode == OP_ICONST) && (data_ptr = initialize_array_data (method, cfg->compile_aot, ip, klass, len_ins->inst_c0, &data_size, &field_token))) {
11569                                 MonoMethod *memcpy_method = get_memcpy_method ();
11570                                 MonoInst *iargs [3];
11571                                 int add_reg = alloc_ireg_mp (cfg);
11572
11573                                 EMIT_NEW_BIALU_IMM (cfg, iargs [0], OP_PADD_IMM, add_reg, ins->dreg, MONO_STRUCT_OFFSET (MonoArray, vector));
11574                                 if (cfg->compile_aot) {
11575                                         EMIT_NEW_AOTCONST_TOKEN (cfg, iargs [1], MONO_PATCH_INFO_RVA, method->klass->image, GPOINTER_TO_UINT(field_token), STACK_PTR, NULL);
11576                                 } else {
11577                                         EMIT_NEW_PCONST (cfg, iargs [1], (char*)data_ptr);
11578                                 }
11579                                 EMIT_NEW_ICONST (cfg, iargs [2], data_size);
11580                                 mono_emit_method_call (cfg, memcpy_method, iargs, NULL);
11581                                 ip += 11;
11582                         }
11583
11584                         break;
11585                 }
11586                 case CEE_LDLEN:
11587                         CHECK_STACK (1);
11588                         --sp;
11589                         if (sp [0]->type != STACK_OBJ)
11590                                 UNVERIFIED;
11591
11592                         MONO_INST_NEW (cfg, ins, OP_LDLEN);
11593                         ins->dreg = alloc_preg (cfg);
11594                         ins->sreg1 = sp [0]->dreg;
11595                         ins->type = STACK_I4;
11596                         /* This flag will be inherited by the decomposition */
11597                         ins->flags |= MONO_INST_FAULT;
11598                         MONO_ADD_INS (cfg->cbb, ins);
11599                         cfg->flags |= MONO_CFG_HAS_ARRAY_ACCESS;
11600                         cfg->cbb->has_array_access = TRUE;
11601                         ip ++;
11602                         *sp++ = ins;
11603                         break;
11604                 case CEE_LDELEMA:
11605                         CHECK_STACK (2);
11606                         sp -= 2;
11607                         CHECK_OPSIZE (5);
11608                         if (sp [0]->type != STACK_OBJ)
11609                                 UNVERIFIED;
11610
11611                         cfg->flags |= MONO_CFG_HAS_LDELEMA;
11612
11613                         klass = mini_get_class (method, read32 (ip + 1), generic_context);
11614                         CHECK_TYPELOAD (klass);
11615                         /* we need to make sure that this array is exactly the type it needs
11616                          * to be for correctness. the wrappers are lax with their usage
11617                          * so we need to ignore them here
11618                          */
11619                         if (!klass->valuetype && method->wrapper_type == MONO_WRAPPER_NONE && !readonly) {
11620                                 MonoClass *array_class = mono_array_class_get (klass, 1);
11621                                 mini_emit_check_array_type (cfg, sp [0], array_class);
11622                                 CHECK_TYPELOAD (array_class);
11623                         }
11624
11625                         readonly = FALSE;
11626                         ins = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], TRUE);
11627                         *sp++ = ins;
11628                         ip += 5;
11629                         break;
11630                 case CEE_LDELEM:
11631                 case CEE_LDELEM_I1:
11632                 case CEE_LDELEM_U1:
11633                 case CEE_LDELEM_I2:
11634                 case CEE_LDELEM_U2:
11635                 case CEE_LDELEM_I4:
11636                 case CEE_LDELEM_U4:
11637                 case CEE_LDELEM_I8:
11638                 case CEE_LDELEM_I:
11639                 case CEE_LDELEM_R4:
11640                 case CEE_LDELEM_R8:
11641                 case CEE_LDELEM_REF: {
11642                         MonoInst *addr;
11643
11644                         CHECK_STACK (2);
11645                         sp -= 2;
11646
11647                         if (*ip == CEE_LDELEM) {
11648                                 CHECK_OPSIZE (5);
11649                                 token = read32 (ip + 1);
11650                                 klass = mini_get_class (method, token, generic_context);
11651                                 CHECK_TYPELOAD (klass);
11652                                 mono_class_init (klass);
11653                         }
11654                         else
11655                                 klass = array_access_to_klass (*ip);
11656
11657                         if (sp [0]->type != STACK_OBJ)
11658                                 UNVERIFIED;
11659
11660                         cfg->flags |= MONO_CFG_HAS_LDELEMA;
11661
11662                         if (mini_is_gsharedvt_variable_klass (klass)) {
11663                                 // FIXME-VT: OP_ICONST optimization
11664                                 addr = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], TRUE);
11665                                 EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, addr->dreg, 0);
11666                                 ins->opcode = OP_LOADV_MEMBASE;
11667                         } else if (sp [1]->opcode == OP_ICONST) {
11668                                 int array_reg = sp [0]->dreg;
11669                                 int index_reg = sp [1]->dreg;
11670                                 int offset = (mono_class_array_element_size (klass) * sp [1]->inst_c0) + MONO_STRUCT_OFFSET (MonoArray, vector);
11671
11672                                 MONO_EMIT_BOUNDS_CHECK (cfg, array_reg, MonoArray, max_length, index_reg);
11673                                 EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, array_reg, offset);
11674                         } else {
11675                                 addr = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], TRUE);
11676                                 EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, addr->dreg, 0);
11677                         }
11678                         *sp++ = ins;
11679                         if (*ip == CEE_LDELEM)
11680                                 ip += 5;
11681                         else
11682                                 ++ip;
11683                         break;
11684                 }
11685                 case CEE_STELEM_I:
11686                 case CEE_STELEM_I1:
11687                 case CEE_STELEM_I2:
11688                 case CEE_STELEM_I4:
11689                 case CEE_STELEM_I8:
11690                 case CEE_STELEM_R4:
11691                 case CEE_STELEM_R8:
11692                 case CEE_STELEM_REF:
11693                 case CEE_STELEM: {
11694                         CHECK_STACK (3);
11695                         sp -= 3;
11696
11697                         cfg->flags |= MONO_CFG_HAS_LDELEMA;
11698
11699                         if (*ip == CEE_STELEM) {
11700                                 CHECK_OPSIZE (5);
11701                                 token = read32 (ip + 1);
11702                                 klass = mini_get_class (method, token, generic_context);
11703                                 CHECK_TYPELOAD (klass);
11704                                 mono_class_init (klass);
11705                         }
11706                         else
11707                                 klass = array_access_to_klass (*ip);
11708
11709                         if (sp [0]->type != STACK_OBJ)
11710                                 UNVERIFIED;
11711
11712                         emit_array_store (cfg, klass, sp, TRUE);
11713
11714                         if (*ip == CEE_STELEM)
11715                                 ip += 5;
11716                         else
11717                                 ++ip;
11718                         inline_costs += 1;
11719                         break;
11720                 }
11721                 case CEE_CKFINITE: {
11722                         CHECK_STACK (1);
11723                         --sp;
11724
11725                         if (cfg->llvm_only) {
11726                                 MonoInst *iargs [1];
11727
11728                                 iargs [0] = sp [0];
11729                                 *sp++ = mono_emit_jit_icall (cfg, mono_ckfinite, iargs);
11730                         } else  {
11731                                 MONO_INST_NEW (cfg, ins, OP_CKFINITE);
11732                                 ins->sreg1 = sp [0]->dreg;
11733                                 ins->dreg = alloc_freg (cfg);
11734                                 ins->type = STACK_R8;
11735                                 MONO_ADD_INS (cfg->cbb, ins);
11736
11737                                 *sp++ = mono_decompose_opcode (cfg, ins);
11738                         }
11739
11740                         ++ip;
11741                         break;
11742                 }
11743                 case CEE_REFANYVAL: {
11744                         MonoInst *src_var, *src;
11745
11746                         int klass_reg = alloc_preg (cfg);
11747                         int dreg = alloc_preg (cfg);
11748
11749                         GSHAREDVT_FAILURE (*ip);
11750
11751                         CHECK_STACK (1);
11752                         MONO_INST_NEW (cfg, ins, *ip);
11753                         --sp;
11754                         CHECK_OPSIZE (5);
11755                         klass = mini_get_class (method, read32 (ip + 1), generic_context);
11756                         CHECK_TYPELOAD (klass);
11757
11758                         context_used = mini_class_check_context_used (cfg, klass);
11759
11760                         // FIXME:
11761                         src_var = get_vreg_to_inst (cfg, sp [0]->dreg);
11762                         if (!src_var)
11763                                 src_var = mono_compile_create_var_for_vreg (cfg, &mono_defaults.typed_reference_class->byval_arg, OP_LOCAL, sp [0]->dreg);
11764                         EMIT_NEW_VARLOADA (cfg, src, src_var, src_var->inst_vtype);
11765                         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, src->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, klass));
11766
11767                         if (context_used) {
11768                                 MonoInst *klass_ins;
11769
11770                                 klass_ins = emit_get_rgctx_klass (cfg, context_used,
11771                                                 klass, MONO_RGCTX_INFO_KLASS);
11772
11773                                 // FIXME:
11774                                 MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, klass_reg, klass_ins->dreg);
11775                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "InvalidCastException");
11776                         } else {
11777                                 mini_emit_class_check (cfg, klass_reg, klass);
11778                         }
11779                         EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, dreg, src->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, value));
11780                         ins->type = STACK_MP;
11781                         ins->klass = klass;
11782                         *sp++ = ins;
11783                         ip += 5;
11784                         break;
11785                 }
11786                 case CEE_MKREFANY: {
11787                         MonoInst *loc, *addr;
11788
11789                         GSHAREDVT_FAILURE (*ip);
11790
11791                         CHECK_STACK (1);
11792                         MONO_INST_NEW (cfg, ins, *ip);
11793                         --sp;
11794                         CHECK_OPSIZE (5);
11795                         klass = mini_get_class (method, read32 (ip + 1), generic_context);
11796                         CHECK_TYPELOAD (klass);
11797
11798                         context_used = mini_class_check_context_used (cfg, klass);
11799
11800                         loc = mono_compile_create_var (cfg, &mono_defaults.typed_reference_class->byval_arg, OP_LOCAL);
11801                         EMIT_NEW_TEMPLOADA (cfg, addr, loc->inst_c0);
11802
11803                         if (context_used) {
11804                                 MonoInst *const_ins;
11805                                 int type_reg = alloc_preg (cfg);
11806
11807                                 const_ins = emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS);
11808                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, klass), const_ins->dreg);
11809                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, type_reg, const_ins->dreg, MONO_STRUCT_OFFSET (MonoClass, byval_arg));
11810                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, type), type_reg);
11811                         } else if (cfg->compile_aot) {
11812                                 int const_reg = alloc_preg (cfg);
11813                                 int type_reg = alloc_preg (cfg);
11814
11815                                 MONO_EMIT_NEW_CLASSCONST (cfg, const_reg, klass);
11816                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, klass), const_reg);
11817                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, type_reg, const_reg, MONO_STRUCT_OFFSET (MonoClass, byval_arg));
11818                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, type), type_reg);
11819                         } else {
11820                                 MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STOREP_MEMBASE_IMM, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, type), &klass->byval_arg);
11821                                 MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STOREP_MEMBASE_IMM, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, klass), klass);
11822                         }
11823                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, value), sp [0]->dreg);
11824
11825                         EMIT_NEW_TEMPLOAD (cfg, ins, loc->inst_c0);
11826                         ins->type = STACK_VTYPE;
11827                         ins->klass = mono_defaults.typed_reference_class;
11828                         *sp++ = ins;
11829                         ip += 5;
11830                         break;
11831                 }
11832                 case CEE_LDTOKEN: {
11833                         gpointer handle;
11834                         MonoClass *handle_class;
11835
11836                         CHECK_STACK_OVF (1);
11837
11838                         CHECK_OPSIZE (5);
11839                         n = read32 (ip + 1);
11840
11841                         if (method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD ||
11842                                         method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED) {
11843                                 handle = mono_method_get_wrapper_data (method, n);
11844                                 handle_class = mono_method_get_wrapper_data (method, n + 1);
11845                                 if (handle_class == mono_defaults.typehandle_class)
11846                                         handle = &((MonoClass*)handle)->byval_arg;
11847                         }
11848                         else {
11849                                 handle = mono_ldtoken_checked (image, n, &handle_class, generic_context, &cfg->error);
11850                                 CHECK_CFG_ERROR;
11851                         }
11852                         if (!handle)
11853                                 LOAD_ERROR;
11854                         mono_class_init (handle_class);
11855                         if (cfg->gshared) {
11856                                 if (mono_metadata_token_table (n) == MONO_TABLE_TYPEDEF ||
11857                                                 mono_metadata_token_table (n) == MONO_TABLE_TYPEREF) {
11858                                         /* This case handles ldtoken
11859                                            of an open type, like for
11860                                            typeof(Gen<>). */
11861                                         context_used = 0;
11862                                 } else if (handle_class == mono_defaults.typehandle_class) {
11863                                         context_used = mini_class_check_context_used (cfg, mono_class_from_mono_type (handle));
11864                                 } else if (handle_class == mono_defaults.fieldhandle_class)
11865                                         context_used = mini_class_check_context_used (cfg, ((MonoClassField*)handle)->parent);
11866                                 else if (handle_class == mono_defaults.methodhandle_class)
11867                                         context_used = mini_method_check_context_used (cfg, handle);
11868                                 else
11869                                         g_assert_not_reached ();
11870                         }
11871
11872                         if ((cfg->opt & MONO_OPT_SHARED) &&
11873                                         method->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD &&
11874                                         method->wrapper_type != MONO_WRAPPER_SYNCHRONIZED) {
11875                                 MonoInst *addr, *vtvar, *iargs [3];
11876                                 int method_context_used;
11877
11878                                 method_context_used = mini_method_check_context_used (cfg, method);
11879
11880                                 vtvar = mono_compile_create_var (cfg, &handle_class->byval_arg, OP_LOCAL); 
11881
11882                                 EMIT_NEW_IMAGECONST (cfg, iargs [0], image);
11883                                 EMIT_NEW_ICONST (cfg, iargs [1], n);
11884                                 if (method_context_used) {
11885                                         iargs [2] = emit_get_rgctx_method (cfg, method_context_used,
11886                                                 method, MONO_RGCTX_INFO_METHOD);
11887                                         ins = mono_emit_jit_icall (cfg, mono_ldtoken_wrapper_generic_shared, iargs);
11888                                 } else {
11889                                         EMIT_NEW_PCONST (cfg, iargs [2], generic_context);
11890                                         ins = mono_emit_jit_icall (cfg, mono_ldtoken_wrapper, iargs);
11891                                 }
11892                                 EMIT_NEW_TEMPLOADA (cfg, addr, vtvar->inst_c0);
11893
11894                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, addr->dreg, 0, ins->dreg);
11895
11896                                 EMIT_NEW_TEMPLOAD (cfg, ins, vtvar->inst_c0);
11897                         } else {
11898                                 if ((ip + 5 < end) && ip_in_bb (cfg, cfg->cbb, ip + 5) && 
11899                                         ((ip [5] == CEE_CALL) || (ip [5] == CEE_CALLVIRT)) && 
11900                                         (cmethod = mini_get_method (cfg, method, read32 (ip + 6), NULL, generic_context)) &&
11901                                         (cmethod->klass == mono_defaults.systemtype_class) &&
11902                                         (strcmp (cmethod->name, "GetTypeFromHandle") == 0)) {
11903                                         MonoClass *tclass = mono_class_from_mono_type (handle);
11904
11905                                         mono_class_init (tclass);
11906                                         if (context_used) {
11907                                                 ins = emit_get_rgctx_klass (cfg, context_used,
11908                                                         tclass, MONO_RGCTX_INFO_REFLECTION_TYPE);
11909                                         } else if (cfg->compile_aot) {
11910                                                 if (method->wrapper_type) {
11911                                                         mono_error_init (&error); //got to do it since there are multiple conditionals below
11912                                                         if (mono_class_get_checked (tclass->image, tclass->type_token, &error) == tclass && !generic_context) {
11913                                                                 /* Special case for static synchronized wrappers */
11914                                                                 EMIT_NEW_TYPE_FROM_HANDLE_CONST (cfg, ins, tclass->image, tclass->type_token, generic_context);
11915                                                         } else {
11916                                                                 mono_error_cleanup (&error); /* FIXME don't swallow the error */
11917                                                                 /* FIXME: n is not a normal token */
11918                                                                 DISABLE_AOT (cfg);
11919                                                                 EMIT_NEW_PCONST (cfg, ins, NULL);
11920                                                         }
11921                                                 } else {
11922                                                         EMIT_NEW_TYPE_FROM_HANDLE_CONST (cfg, ins, image, n, generic_context);
11923                                                 }
11924                                         } else {
11925                                                 EMIT_NEW_PCONST (cfg, ins, mono_type_get_object (cfg->domain, handle));
11926                                         }
11927                                         ins->type = STACK_OBJ;
11928                                         ins->klass = cmethod->klass;
11929                                         ip += 5;
11930                                 } else {
11931                                         MonoInst *addr, *vtvar;
11932
11933                                         vtvar = mono_compile_create_var (cfg, &handle_class->byval_arg, OP_LOCAL);
11934
11935                                         if (context_used) {
11936                                                 if (handle_class == mono_defaults.typehandle_class) {
11937                                                         ins = emit_get_rgctx_klass (cfg, context_used,
11938                                                                         mono_class_from_mono_type (handle),
11939                                                                         MONO_RGCTX_INFO_TYPE);
11940                                                 } else if (handle_class == mono_defaults.methodhandle_class) {
11941                                                         ins = emit_get_rgctx_method (cfg, context_used,
11942                                                                         handle, MONO_RGCTX_INFO_METHOD);
11943                                                 } else if (handle_class == mono_defaults.fieldhandle_class) {
11944                                                         ins = emit_get_rgctx_field (cfg, context_used,
11945                                                                         handle, MONO_RGCTX_INFO_CLASS_FIELD);
11946                                                 } else {
11947                                                         g_assert_not_reached ();
11948                                                 }
11949                                         } else if (cfg->compile_aot) {
11950                                                 EMIT_NEW_LDTOKENCONST (cfg, ins, image, n, generic_context);
11951                                         } else {
11952                                                 EMIT_NEW_PCONST (cfg, ins, handle);
11953                                         }
11954                                         EMIT_NEW_TEMPLOADA (cfg, addr, vtvar->inst_c0);
11955                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, addr->dreg, 0, ins->dreg);
11956                                         EMIT_NEW_TEMPLOAD (cfg, ins, vtvar->inst_c0);
11957                                 }
11958                         }
11959
11960                         *sp++ = ins;
11961                         ip += 5;
11962                         break;
11963                 }
11964                 case CEE_THROW:
11965                         CHECK_STACK (1);
11966                         MONO_INST_NEW (cfg, ins, OP_THROW);
11967                         --sp;
11968                         ins->sreg1 = sp [0]->dreg;
11969                         ip++;
11970                         cfg->cbb->out_of_line = TRUE;
11971                         MONO_ADD_INS (cfg->cbb, ins);
11972                         MONO_INST_NEW (cfg, ins, OP_NOT_REACHED);
11973                         MONO_ADD_INS (cfg->cbb, ins);
11974                         sp = stack_start;
11975                         
11976                         link_bblock (cfg, cfg->cbb, end_bblock);
11977                         start_new_bblock = 1;
11978                         /* This can complicate code generation for llvm since the return value might not be defined */
11979                         if (COMPILE_LLVM (cfg))
11980                                 INLINE_FAILURE ("throw");
11981                         break;
11982                 case CEE_ENDFINALLY:
11983                         /* mono_save_seq_point_info () depends on this */
11984                         if (sp != stack_start)
11985                                 emit_seq_point (cfg, method, ip, FALSE, FALSE);
11986                         MONO_INST_NEW (cfg, ins, OP_ENDFINALLY);
11987                         MONO_ADD_INS (cfg->cbb, ins);
11988                         ip++;
11989                         start_new_bblock = 1;
11990
11991                         /*
11992                          * Control will leave the method so empty the stack, otherwise
11993                          * the next basic block will start with a nonempty stack.
11994                          */
11995                         while (sp != stack_start) {
11996                                 sp--;
11997                         }
11998                         break;
11999                 case CEE_LEAVE:
12000                 case CEE_LEAVE_S: {
12001                         GList *handlers;
12002
12003                         if (*ip == CEE_LEAVE) {
12004                                 CHECK_OPSIZE (5);
12005                                 target = ip + 5 + (gint32)read32(ip + 1);
12006                         } else {
12007                                 CHECK_OPSIZE (2);
12008                                 target = ip + 2 + (signed char)(ip [1]);
12009                         }
12010
12011                         /* empty the stack */
12012                         while (sp != stack_start) {
12013                                 sp--;
12014                         }
12015
12016                         /* 
12017                          * If this leave statement is in a catch block, check for a
12018                          * pending exception, and rethrow it if necessary.
12019                          * We avoid doing this in runtime invoke wrappers, since those are called
12020                          * by native code which excepts the wrapper to catch all exceptions.
12021                          */
12022                         for (i = 0; i < header->num_clauses; ++i) {
12023                                 MonoExceptionClause *clause = &header->clauses [i];
12024
12025                                 /* 
12026                                  * Use <= in the final comparison to handle clauses with multiple
12027                                  * leave statements, like in bug #78024.
12028                                  * The ordering of the exception clauses guarantees that we find the
12029                                  * innermost clause.
12030                                  */
12031                                 if (MONO_OFFSET_IN_HANDLER (clause, ip - header->code) && (clause->flags == MONO_EXCEPTION_CLAUSE_NONE) && (ip - header->code + ((*ip == CEE_LEAVE) ? 5 : 2)) <= (clause->handler_offset + clause->handler_len) && method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE) {
12032                                         MonoInst *exc_ins;
12033                                         MonoBasicBlock *dont_throw;
12034
12035                                         /*
12036                                           MonoInst *load;
12037
12038                                           NEW_TEMPLOAD (cfg, load, mono_find_exvar_for_offset (cfg, clause->handler_offset)->inst_c0);
12039                                         */
12040
12041                                         exc_ins = mono_emit_jit_icall (cfg, mono_thread_get_undeniable_exception, NULL);
12042
12043                                         NEW_BBLOCK (cfg, dont_throw);
12044
12045                                         /*
12046                                          * Currently, we always rethrow the abort exception, despite the 
12047                                          * fact that this is not correct. See thread6.cs for an example. 
12048                                          * But propagating the abort exception is more important than 
12049                                          * getting the sematics right.
12050                                          */
12051                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, exc_ins->dreg, 0);
12052                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, dont_throw);
12053                                         MONO_EMIT_NEW_UNALU (cfg, OP_THROW, -1, exc_ins->dreg);
12054
12055                                         MONO_START_BB (cfg, dont_throw);
12056                                 }
12057                         }
12058
12059 #ifdef ENABLE_LLVM
12060                         cfg->cbb->try_end = (intptr_t)(ip - header->code);
12061 #endif
12062
12063                         if ((handlers = mono_find_final_block (cfg, ip, target, MONO_EXCEPTION_CLAUSE_FINALLY))) {
12064                                 GList *tmp;
12065                                 MonoExceptionClause *clause;
12066
12067                                 for (tmp = handlers; tmp; tmp = tmp->next) {
12068                                         clause = tmp->data;
12069                                         tblock = cfg->cil_offset_to_bb [clause->handler_offset];
12070                                         g_assert (tblock);
12071                                         link_bblock (cfg, cfg->cbb, tblock);
12072                                         MONO_INST_NEW (cfg, ins, OP_CALL_HANDLER);
12073                                         ins->inst_target_bb = tblock;
12074                                         ins->inst_eh_block = clause;
12075                                         MONO_ADD_INS (cfg->cbb, ins);
12076                                         cfg->cbb->has_call_handler = 1;
12077                                         if (COMPILE_LLVM (cfg)) {
12078                                                 MonoBasicBlock *target_bb;
12079
12080                                                 /* 
12081                                                  * Link the finally bblock with the target, since it will
12082                                                  * conceptually branch there.
12083                                                  * FIXME: Have to link the bblock containing the endfinally.
12084                                                  */
12085                                                 GET_BBLOCK (cfg, target_bb, target);
12086                                                 link_bblock (cfg, tblock, target_bb);
12087                                         }
12088                                 }
12089                                 g_list_free (handlers);
12090                         } 
12091
12092                         MONO_INST_NEW (cfg, ins, OP_BR);
12093                         MONO_ADD_INS (cfg->cbb, ins);
12094                         GET_BBLOCK (cfg, tblock, target);
12095                         link_bblock (cfg, cfg->cbb, tblock);
12096                         ins->inst_target_bb = tblock;
12097
12098                         start_new_bblock = 1;
12099
12100                         if (*ip == CEE_LEAVE)
12101                                 ip += 5;
12102                         else
12103                                 ip += 2;
12104
12105                         break;
12106                 }
12107
12108                         /*
12109                          * Mono specific opcodes
12110                          */
12111                 case MONO_CUSTOM_PREFIX: {
12112
12113                         g_assert (method->wrapper_type != MONO_WRAPPER_NONE);
12114
12115                         CHECK_OPSIZE (2);
12116                         switch (ip [1]) {
12117                         case CEE_MONO_ICALL: {
12118                                 gpointer func;
12119                                 MonoJitICallInfo *info;
12120
12121                                 token = read32 (ip + 2);
12122                                 func = mono_method_get_wrapper_data (method, token);
12123                                 info = mono_find_jit_icall_by_addr (func);
12124                                 if (!info)
12125                                         g_error ("Could not find icall address in wrapper %s", mono_method_full_name (method, 1));
12126                                 g_assert (info);
12127
12128                                 CHECK_STACK (info->sig->param_count);
12129                                 sp -= info->sig->param_count;
12130
12131                                 ins = mono_emit_jit_icall (cfg, info->func, sp);
12132                                 if (!MONO_TYPE_IS_VOID (info->sig->ret))
12133                                         *sp++ = ins;
12134
12135                                 ip += 6;
12136                                 inline_costs += 10 * num_calls++;
12137
12138                                 break;
12139                         }
12140                         case CEE_MONO_LDPTR_CARD_TABLE: {
12141                                 int shift_bits;
12142                                 gpointer card_mask;
12143                                 CHECK_STACK_OVF (1);
12144
12145                                 if (cfg->compile_aot)
12146                                         EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_GC_CARD_TABLE_ADDR, NULL);
12147                                 else
12148                                         EMIT_NEW_PCONST (cfg, ins, mono_gc_get_card_table (&shift_bits, &card_mask));
12149
12150                                 *sp++ = ins;
12151                                 ip += 2;
12152                                 inline_costs += 10 * num_calls++;
12153                                 break;
12154                         }
12155                         case CEE_MONO_LDPTR_NURSERY_START: {
12156                                 int shift_bits;
12157                                 size_t size;
12158                                 CHECK_STACK_OVF (1);
12159
12160                                 if (cfg->compile_aot)
12161                                         EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_GC_NURSERY_START, NULL);
12162                                 else
12163                                         EMIT_NEW_PCONST (cfg, ins, mono_gc_get_nursery (&shift_bits, &size));
12164
12165                                 *sp++ = ins;
12166                                 ip += 2;
12167                                 inline_costs += 10 * num_calls++;
12168                                 break;
12169                         }
12170                         case CEE_MONO_LDPTR_INT_REQ_FLAG: {
12171                                 CHECK_STACK_OVF (1);
12172
12173                                 if (cfg->compile_aot)
12174                                         EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG, NULL);
12175                                 else
12176                                         EMIT_NEW_PCONST (cfg, ins, mono_thread_interruption_request_flag ());
12177
12178                                 *sp++ = ins;
12179                                 ip += 2;
12180                                 inline_costs += 10 * num_calls++;
12181                                 break;
12182                         }
12183                         case CEE_MONO_LDPTR: {
12184                                 gpointer ptr;
12185
12186                                 CHECK_STACK_OVF (1);
12187                                 CHECK_OPSIZE (6);
12188                                 token = read32 (ip + 2);
12189
12190                                 ptr = mono_method_get_wrapper_data (method, token);
12191                                 EMIT_NEW_PCONST (cfg, ins, ptr);
12192                                 *sp++ = ins;
12193                                 ip += 6;
12194                                 inline_costs += 10 * num_calls++;
12195                                 /* Can't embed random pointers into AOT code */
12196                                 DISABLE_AOT (cfg);
12197                                 break;
12198                         }
12199                         case CEE_MONO_JIT_ICALL_ADDR: {
12200                                 MonoJitICallInfo *callinfo;
12201                                 gpointer ptr;
12202
12203                                 CHECK_STACK_OVF (1);
12204                                 CHECK_OPSIZE (6);
12205                                 token = read32 (ip + 2);
12206
12207                                 ptr = mono_method_get_wrapper_data (method, token);
12208                                 callinfo = mono_find_jit_icall_by_addr (ptr);
12209                                 g_assert (callinfo);
12210                                 EMIT_NEW_JIT_ICALL_ADDRCONST (cfg, ins, (char*)callinfo->name);
12211                                 *sp++ = ins;
12212                                 ip += 6;
12213                                 inline_costs += 10 * num_calls++;
12214                                 break;
12215                         }
12216                         case CEE_MONO_ICALL_ADDR: {
12217                                 MonoMethod *cmethod;
12218                                 gpointer ptr;
12219
12220                                 CHECK_STACK_OVF (1);
12221                                 CHECK_OPSIZE (6);
12222                                 token = read32 (ip + 2);
12223
12224                                 cmethod = mono_method_get_wrapper_data (method, token);
12225
12226                                 if (cfg->compile_aot) {
12227                                         EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_ICALL_ADDR, cmethod);
12228                                 } else {
12229                                         ptr = mono_lookup_internal_call (cmethod);
12230                                         g_assert (ptr);
12231                                         EMIT_NEW_PCONST (cfg, ins, ptr);
12232                                 }
12233                                 *sp++ = ins;
12234                                 ip += 6;
12235                                 break;
12236                         }
12237                         case CEE_MONO_VTADDR: {
12238                                 MonoInst *src_var, *src;
12239
12240                                 CHECK_STACK (1);
12241                                 --sp;
12242
12243                                 // FIXME:
12244                                 src_var = get_vreg_to_inst (cfg, sp [0]->dreg);
12245                                 EMIT_NEW_VARLOADA ((cfg), (src), src_var, src_var->inst_vtype);
12246                                 *sp++ = src;
12247                                 ip += 2;
12248                                 break;
12249                         }
12250                         case CEE_MONO_NEWOBJ: {
12251                                 MonoInst *iargs [2];
12252
12253                                 CHECK_STACK_OVF (1);
12254                                 CHECK_OPSIZE (6);
12255                                 token = read32 (ip + 2);
12256                                 klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
12257                                 mono_class_init (klass);
12258                                 NEW_DOMAINCONST (cfg, iargs [0]);
12259                                 MONO_ADD_INS (cfg->cbb, iargs [0]);
12260                                 NEW_CLASSCONST (cfg, iargs [1], klass);
12261                                 MONO_ADD_INS (cfg->cbb, iargs [1]);
12262                                 *sp++ = mono_emit_jit_icall (cfg, mono_object_new, iargs);
12263                                 ip += 6;
12264                                 inline_costs += 10 * num_calls++;
12265                                 break;
12266                         }
12267                         case CEE_MONO_OBJADDR:
12268                                 CHECK_STACK (1);
12269                                 --sp;
12270                                 MONO_INST_NEW (cfg, ins, OP_MOVE);
12271                                 ins->dreg = alloc_ireg_mp (cfg);
12272                                 ins->sreg1 = sp [0]->dreg;
12273                                 ins->type = STACK_MP;
12274                                 MONO_ADD_INS (cfg->cbb, ins);
12275                                 *sp++ = ins;
12276                                 ip += 2;
12277                                 break;
12278                         case CEE_MONO_LDNATIVEOBJ:
12279                                 /*
12280                                  * Similar to LDOBJ, but instead load the unmanaged 
12281                                  * representation of the vtype to the stack.
12282                                  */
12283                                 CHECK_STACK (1);
12284                                 CHECK_OPSIZE (6);
12285                                 --sp;
12286                                 token = read32 (ip + 2);
12287                                 klass = mono_method_get_wrapper_data (method, token);
12288                                 g_assert (klass->valuetype);
12289                                 mono_class_init (klass);
12290
12291                                 {
12292                                         MonoInst *src, *dest, *temp;
12293
12294                                         src = sp [0];
12295                                         temp = mono_compile_create_var (cfg, &klass->byval_arg, OP_LOCAL);
12296                                         temp->backend.is_pinvoke = 1;
12297                                         EMIT_NEW_TEMPLOADA (cfg, dest, temp->inst_c0);
12298                                         mini_emit_stobj (cfg, dest, src, klass, TRUE);
12299
12300                                         EMIT_NEW_TEMPLOAD (cfg, dest, temp->inst_c0);
12301                                         dest->type = STACK_VTYPE;
12302                                         dest->klass = klass;
12303
12304                                         *sp ++ = dest;
12305                                         ip += 6;
12306                                 }
12307                                 break;
12308                         case CEE_MONO_RETOBJ: {
12309                                 /*
12310                                  * Same as RET, but return the native representation of a vtype
12311                                  * to the caller.
12312                                  */
12313                                 g_assert (cfg->ret);
12314                                 g_assert (mono_method_signature (method)->pinvoke); 
12315                                 CHECK_STACK (1);
12316                                 --sp;
12317                                 
12318                                 CHECK_OPSIZE (6);
12319                                 token = read32 (ip + 2);    
12320                                 klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
12321
12322                                 if (!cfg->vret_addr) {
12323                                         g_assert (cfg->ret_var_is_local);
12324
12325                                         EMIT_NEW_VARLOADA (cfg, ins, cfg->ret, cfg->ret->inst_vtype);
12326                                 } else {
12327                                         EMIT_NEW_RETLOADA (cfg, ins);
12328                                 }
12329                                 mini_emit_stobj (cfg, ins, sp [0], klass, TRUE);
12330                                 
12331                                 if (sp != stack_start)
12332                                         UNVERIFIED;
12333                                 
12334                                 MONO_INST_NEW (cfg, ins, OP_BR);
12335                                 ins->inst_target_bb = end_bblock;
12336                                 MONO_ADD_INS (cfg->cbb, ins);
12337                                 link_bblock (cfg, cfg->cbb, end_bblock);
12338                                 start_new_bblock = 1;
12339                                 ip += 6;
12340                                 break;
12341                         }
12342                         case CEE_MONO_CISINST:
12343                         case CEE_MONO_CCASTCLASS: {
12344                                 int token;
12345                                 CHECK_STACK (1);
12346                                 --sp;
12347                                 CHECK_OPSIZE (6);
12348                                 token = read32 (ip + 2);
12349                                 klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
12350                                 if (ip [1] == CEE_MONO_CISINST)
12351                                         ins = handle_cisinst (cfg, klass, sp [0]);
12352                                 else
12353                                         ins = handle_ccastclass (cfg, klass, sp [0]);
12354                                 *sp++ = ins;
12355                                 ip += 6;
12356                                 break;
12357                         }
12358                         case CEE_MONO_SAVE_LMF:
12359                         case CEE_MONO_RESTORE_LMF:
12360                                 ip += 2;
12361                                 break;
12362                         case CEE_MONO_CLASSCONST:
12363                                 CHECK_STACK_OVF (1);
12364                                 CHECK_OPSIZE (6);
12365                                 token = read32 (ip + 2);
12366                                 EMIT_NEW_CLASSCONST (cfg, ins, mono_method_get_wrapper_data (method, token));
12367                                 *sp++ = ins;
12368                                 ip += 6;
12369                                 inline_costs += 10 * num_calls++;
12370                                 break;
12371                         case CEE_MONO_NOT_TAKEN:
12372                                 cfg->cbb->out_of_line = TRUE;
12373                                 ip += 2;
12374                                 break;
12375                         case CEE_MONO_TLS: {
12376                                 int key;
12377
12378                                 CHECK_STACK_OVF (1);
12379                                 CHECK_OPSIZE (6);
12380                                 key = (gint32)read32 (ip + 2);
12381                                 g_assert (key < TLS_KEY_NUM);
12382
12383                                 ins = mono_create_tls_get (cfg, key);
12384                                 if (!ins) {
12385                                         if (cfg->compile_aot) {
12386                                                 DISABLE_AOT (cfg);
12387                                                 MONO_INST_NEW (cfg, ins, OP_TLS_GET);
12388                                                 ins->dreg = alloc_preg (cfg);
12389                                                 ins->type = STACK_PTR;
12390                                         } else {
12391                                                 g_assert_not_reached ();
12392                                         }
12393                                 }
12394                                 ins->type = STACK_PTR;
12395                                 MONO_ADD_INS (cfg->cbb, ins);
12396                                 *sp++ = ins;
12397                                 ip += 6;
12398                                 break;
12399                         }
12400                         case CEE_MONO_DYN_CALL: {
12401                                 MonoCallInst *call;
12402
12403                                 /* It would be easier to call a trampoline, but that would put an
12404                                  * extra frame on the stack, confusing exception handling. So
12405                                  * implement it inline using an opcode for now.
12406                                  */
12407
12408                                 if (!cfg->dyn_call_var) {
12409                                         cfg->dyn_call_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
12410                                         /* prevent it from being register allocated */
12411                                         cfg->dyn_call_var->flags |= MONO_INST_VOLATILE;
12412                                 }
12413
12414                                 /* Has to use a call inst since it local regalloc expects it */
12415                                 MONO_INST_NEW_CALL (cfg, call, OP_DYN_CALL);
12416                                 ins = (MonoInst*)call;
12417                                 sp -= 2;
12418                                 ins->sreg1 = sp [0]->dreg;
12419                                 ins->sreg2 = sp [1]->dreg;
12420                                 MONO_ADD_INS (cfg->cbb, ins);
12421
12422                                 cfg->param_area = MAX (cfg->param_area, cfg->backend->dyn_call_param_area);
12423
12424                                 ip += 2;
12425                                 inline_costs += 10 * num_calls++;
12426
12427                                 break;
12428                         }
12429                         case CEE_MONO_MEMORY_BARRIER: {
12430                                 CHECK_OPSIZE (6);
12431                                 emit_memory_barrier (cfg, (int)read32 (ip + 2));
12432                                 ip += 6;
12433                                 break;
12434                         }
12435                         case CEE_MONO_JIT_ATTACH: {
12436                                 MonoInst *args [16], *domain_ins;
12437                                 MonoInst *ad_ins, *jit_tls_ins;
12438                                 MonoBasicBlock *next_bb = NULL, *call_bb = NULL;
12439
12440                                 cfg->orig_domain_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
12441
12442                                 EMIT_NEW_PCONST (cfg, ins, NULL);
12443                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->orig_domain_var->dreg, ins->dreg);
12444
12445                                 ad_ins = mono_get_domain_intrinsic (cfg);
12446                                 jit_tls_ins = mono_get_jit_tls_intrinsic (cfg);
12447
12448                                 if (cfg->backend->have_tls_get && ad_ins && jit_tls_ins) {
12449                                         NEW_BBLOCK (cfg, next_bb);
12450                                         NEW_BBLOCK (cfg, call_bb);
12451
12452                                         if (cfg->compile_aot) {
12453                                                 /* AOT code is only used in the root domain */
12454                                                 EMIT_NEW_PCONST (cfg, domain_ins, NULL);
12455                                         } else {
12456                                                 EMIT_NEW_PCONST (cfg, domain_ins, cfg->domain);
12457                                         }
12458                                         MONO_ADD_INS (cfg->cbb, ad_ins);
12459                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, ad_ins->dreg, domain_ins->dreg);
12460                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, call_bb);
12461
12462                                         MONO_ADD_INS (cfg->cbb, jit_tls_ins);
12463                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, jit_tls_ins->dreg, 0);
12464                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, call_bb);
12465
12466                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, next_bb);
12467                                         MONO_START_BB (cfg, call_bb);
12468                                 }
12469
12470                                 if (cfg->compile_aot) {
12471                                         /* AOT code is only used in the root domain */
12472                                         EMIT_NEW_PCONST (cfg, args [0], NULL);
12473                                 } else {
12474                                         EMIT_NEW_PCONST (cfg, args [0], cfg->domain);
12475                                 }
12476                                 ins = mono_emit_jit_icall (cfg, mono_jit_thread_attach, args);
12477                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->orig_domain_var->dreg, ins->dreg);
12478
12479                                 if (next_bb)
12480                                         MONO_START_BB (cfg, next_bb);
12481                                 ip += 2;
12482                                 break;
12483                         }
12484                         case CEE_MONO_JIT_DETACH: {
12485                                 MonoInst *args [16];
12486
12487                                 /* Restore the original domain */
12488                                 dreg = alloc_ireg (cfg);
12489                                 EMIT_NEW_UNALU (cfg, args [0], OP_MOVE, dreg, cfg->orig_domain_var->dreg);
12490                                 mono_emit_jit_icall (cfg, mono_jit_set_domain, args);
12491                                 ip += 2;
12492                                 break;
12493                         }
12494                         default:
12495                                 g_error ("opcode 0x%02x 0x%02x not handled", MONO_CUSTOM_PREFIX, ip [1]);
12496                                 break;
12497                         }
12498                         break;
12499                 }
12500
12501                 case CEE_PREFIX1: {
12502                         CHECK_OPSIZE (2);
12503                         switch (ip [1]) {
12504                         case CEE_ARGLIST: {
12505                                 /* somewhat similar to LDTOKEN */
12506                                 MonoInst *addr, *vtvar;
12507                                 CHECK_STACK_OVF (1);
12508                                 vtvar = mono_compile_create_var (cfg, &mono_defaults.argumenthandle_class->byval_arg, OP_LOCAL); 
12509
12510                                 EMIT_NEW_TEMPLOADA (cfg, addr, vtvar->inst_c0);
12511                                 EMIT_NEW_UNALU (cfg, ins, OP_ARGLIST, -1, addr->dreg);
12512
12513                                 EMIT_NEW_TEMPLOAD (cfg, ins, vtvar->inst_c0);
12514                                 ins->type = STACK_VTYPE;
12515                                 ins->klass = mono_defaults.argumenthandle_class;
12516                                 *sp++ = ins;
12517                                 ip += 2;
12518                                 break;
12519                         }
12520                         case CEE_CEQ:
12521                         case CEE_CGT:
12522                         case CEE_CGT_UN:
12523                         case CEE_CLT:
12524                         case CEE_CLT_UN: {
12525                                 MonoInst *cmp, *arg1, *arg2;
12526
12527                                 CHECK_STACK (2);
12528                                 sp -= 2;
12529                                 arg1 = sp [0];
12530                                 arg2 = sp [1];
12531
12532                                 /*
12533                                  * The following transforms:
12534                                  *    CEE_CEQ    into OP_CEQ
12535                                  *    CEE_CGT    into OP_CGT
12536                                  *    CEE_CGT_UN into OP_CGT_UN
12537                                  *    CEE_CLT    into OP_CLT
12538                                  *    CEE_CLT_UN into OP_CLT_UN
12539                                  */
12540                                 MONO_INST_NEW (cfg, cmp, (OP_CEQ - CEE_CEQ) + ip [1]);
12541
12542                                 MONO_INST_NEW (cfg, ins, cmp->opcode);
12543                                 cmp->sreg1 = arg1->dreg;
12544                                 cmp->sreg2 = arg2->dreg;
12545                                 type_from_op (cfg, cmp, arg1, arg2);
12546                                 CHECK_TYPE (cmp);
12547                                 add_widen_op (cfg, cmp, &arg1, &arg2);
12548                                 if ((arg1->type == STACK_I8) || ((SIZEOF_VOID_P == 8) && ((arg1->type == STACK_PTR) || (arg1->type == STACK_OBJ) || (arg1->type == STACK_MP))))
12549                                         cmp->opcode = OP_LCOMPARE;
12550                                 else if (arg1->type == STACK_R4)
12551                                         cmp->opcode = OP_RCOMPARE;
12552                                 else if (arg1->type == STACK_R8)
12553                                         cmp->opcode = OP_FCOMPARE;
12554                                 else
12555                                         cmp->opcode = OP_ICOMPARE;
12556                                 MONO_ADD_INS (cfg->cbb, cmp);
12557                                 ins->type = STACK_I4;
12558                                 ins->dreg = alloc_dreg (cfg, ins->type);
12559                                 type_from_op (cfg, ins, arg1, arg2);
12560
12561                                 if (cmp->opcode == OP_FCOMPARE || cmp->opcode == OP_RCOMPARE) {
12562                                         /*
12563                                          * The backends expect the fceq opcodes to do the
12564                                          * comparison too.
12565                                          */
12566                                         ins->sreg1 = cmp->sreg1;
12567                                         ins->sreg2 = cmp->sreg2;
12568                                         NULLIFY_INS (cmp);
12569                                 }
12570                                 MONO_ADD_INS (cfg->cbb, ins);
12571                                 *sp++ = ins;
12572                                 ip += 2;
12573                                 break;
12574                         }
12575                         case CEE_LDFTN: {
12576                                 MonoInst *argconst;
12577                                 MonoMethod *cil_method;
12578
12579                                 CHECK_STACK_OVF (1);
12580                                 CHECK_OPSIZE (6);
12581                                 n = read32 (ip + 2);
12582                                 cmethod = mini_get_method (cfg, method, n, NULL, generic_context);
12583                                 if (!cmethod || mono_loader_get_last_error ())
12584                                         LOAD_ERROR;
12585                                 mono_class_init (cmethod->klass);
12586
12587                                 mono_save_token_info (cfg, image, n, cmethod);
12588
12589                                 context_used = mini_method_check_context_used (cfg, cmethod);
12590
12591                                 cil_method = cmethod;
12592                                 if (!dont_verify && !cfg->skip_visibility && !mono_method_can_access_method (method, cmethod))
12593                                         METHOD_ACCESS_FAILURE (method, cil_method);
12594
12595                                 if (mono_security_core_clr_enabled ())
12596                                         ensure_method_is_allowed_to_call_method (cfg, method, cmethod);
12597
12598                                 /* 
12599                                  * Optimize the common case of ldftn+delegate creation
12600                                  */
12601                                 if ((sp > stack_start) && (ip + 6 + 5 < end) && ip_in_bb (cfg, cfg->cbb, ip + 6) && (ip [6] == CEE_NEWOBJ)) {
12602                                         MonoMethod *ctor_method = mini_get_method (cfg, method, read32 (ip + 7), NULL, generic_context);
12603                                         if (ctor_method && (ctor_method->klass->parent == mono_defaults.multicastdelegate_class)) {
12604                                                 MonoInst *target_ins, *handle_ins;
12605                                                 MonoMethod *invoke;
12606                                                 int invoke_context_used;
12607
12608                                                 invoke = mono_get_delegate_invoke (ctor_method->klass);
12609                                                 if (!invoke || !mono_method_signature (invoke))
12610                                                         LOAD_ERROR;
12611
12612                                                 invoke_context_used = mini_method_check_context_used (cfg, invoke);
12613
12614                                                 target_ins = sp [-1];
12615
12616                                                 if (mono_security_core_clr_enabled ())
12617                                                         ensure_method_is_allowed_to_call_method (cfg, method, ctor_method);
12618
12619                                                 if (!(cmethod->flags & METHOD_ATTRIBUTE_STATIC)) {
12620                                                         /*LAME IMPL: We must not add a null check for virtual invoke delegates.*/
12621                                                         if (mono_method_signature (invoke)->param_count == mono_method_signature (cmethod)->param_count) {
12622                                                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, target_ins->dreg, 0);
12623                                                                 MONO_EMIT_NEW_COND_EXC (cfg, EQ, "ArgumentException");
12624                                                         }
12625                                                 }
12626
12627                                                 /* FIXME: SGEN support */
12628                                                 if (invoke_context_used == 0) {
12629                                                         ip += 6;
12630                                                         if (cfg->verbose_level > 3)
12631                                                                 g_print ("converting (in B%d: stack: %d) %s", cfg->cbb->block_num, (int)(sp - stack_start), mono_disasm_code_one (NULL, method, ip, NULL));
12632                                                         if ((handle_ins = handle_delegate_ctor (cfg, ctor_method->klass, target_ins, cmethod, context_used, FALSE))) {
12633                                                                 sp --;
12634                                                                 *sp = handle_ins;
12635                                                                 CHECK_CFG_EXCEPTION;
12636                                                                 ip += 5;
12637                                                                 sp ++;
12638                                                                 break;
12639                                                         }
12640                                                         ip -= 6;
12641                                                 }
12642                                         }
12643                                 }
12644
12645                                 argconst = emit_get_rgctx_method (cfg, context_used, cmethod, MONO_RGCTX_INFO_METHOD);
12646                                 ins = mono_emit_jit_icall (cfg, mono_ldftn, &argconst);
12647                                 *sp++ = ins;
12648                                 
12649                                 ip += 6;
12650                                 inline_costs += 10 * num_calls++;
12651                                 break;
12652                         }
12653                         case CEE_LDVIRTFTN: {
12654                                 MonoInst *args [2];
12655
12656                                 CHECK_STACK (1);
12657                                 CHECK_OPSIZE (6);
12658                                 n = read32 (ip + 2);
12659                                 cmethod = mini_get_method (cfg, method, n, NULL, generic_context);
12660                                 if (!cmethod || mono_loader_get_last_error ())
12661                                         LOAD_ERROR;
12662                                 mono_class_init (cmethod->klass);
12663  
12664                                 context_used = mini_method_check_context_used (cfg, cmethod);
12665
12666                                 if (mono_security_core_clr_enabled ())
12667                                         ensure_method_is_allowed_to_call_method (cfg, method, cmethod);
12668
12669                                 /*
12670                                  * Optimize the common case of ldvirtftn+delegate creation
12671                                  */
12672                                 if ((sp > stack_start) && (ip + 6 + 5 < end) && ip_in_bb (cfg, cfg->cbb, ip + 6) && (ip [6] == CEE_NEWOBJ) && (ip > header->code && ip [-1] == CEE_DUP)) {
12673                                         MonoMethod *ctor_method = mini_get_method (cfg, method, read32 (ip + 7), NULL, generic_context);
12674                                         if (ctor_method && (ctor_method->klass->parent == mono_defaults.multicastdelegate_class)) {
12675                                                 MonoInst *target_ins, *handle_ins;
12676                                                 MonoMethod *invoke;
12677                                                 int invoke_context_used;
12678                                                 gboolean is_virtual = cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL;
12679
12680                                                 invoke = mono_get_delegate_invoke (ctor_method->klass);
12681                                                 if (!invoke || !mono_method_signature (invoke))
12682                                                         LOAD_ERROR;
12683
12684                                                 invoke_context_used = mini_method_check_context_used (cfg, invoke);
12685
12686                                                 target_ins = sp [-1];
12687
12688                                                 if (mono_security_core_clr_enabled ())
12689                                                         ensure_method_is_allowed_to_call_method (cfg, method, ctor_method);
12690
12691                                                 /* FIXME: SGEN support */
12692                                                 if (invoke_context_used == 0 || cfg->llvm_only) {
12693                                                         ip += 6;
12694                                                         if (cfg->verbose_level > 3)
12695                                                                 g_print ("converting (in B%d: stack: %d) %s", cfg->cbb->block_num, (int)(sp - stack_start), mono_disasm_code_one (NULL, method, ip, NULL));
12696                                                         if ((handle_ins = handle_delegate_ctor (cfg, ctor_method->klass, target_ins, cmethod, context_used, is_virtual))) {
12697                                                                 sp -= 2;
12698                                                                 *sp = handle_ins;
12699                                                                 CHECK_CFG_EXCEPTION;
12700                                                                 ip += 5;
12701                                                                 sp ++;
12702                                                                 break;
12703                                                         }
12704                                                         ip -= 6;
12705                                                 }
12706                                         }
12707                                 }
12708
12709                                 --sp;
12710                                 args [0] = *sp;
12711
12712                                 args [1] = emit_get_rgctx_method (cfg, context_used,
12713                                                                                                   cmethod, MONO_RGCTX_INFO_METHOD);
12714
12715                                 if (context_used)
12716                                         *sp++ = mono_emit_jit_icall (cfg, mono_ldvirtfn_gshared, args);
12717                                 else
12718                                         *sp++ = mono_emit_jit_icall (cfg, mono_ldvirtfn, args);
12719
12720                                 ip += 6;
12721                                 inline_costs += 10 * num_calls++;
12722                                 break;
12723                         }
12724                         case CEE_LDARG:
12725                                 CHECK_STACK_OVF (1);
12726                                 CHECK_OPSIZE (4);
12727                                 n = read16 (ip + 2);
12728                                 CHECK_ARG (n);
12729                                 EMIT_NEW_ARGLOAD (cfg, ins, n);
12730                                 *sp++ = ins;
12731                                 ip += 4;
12732                                 break;
12733                         case CEE_LDARGA:
12734                                 CHECK_STACK_OVF (1);
12735                                 CHECK_OPSIZE (4);
12736                                 n = read16 (ip + 2);
12737                                 CHECK_ARG (n);
12738                                 NEW_ARGLOADA (cfg, ins, n);
12739                                 MONO_ADD_INS (cfg->cbb, ins);
12740                                 *sp++ = ins;
12741                                 ip += 4;
12742                                 break;
12743                         case CEE_STARG:
12744                                 CHECK_STACK (1);
12745                                 --sp;
12746                                 CHECK_OPSIZE (4);
12747                                 n = read16 (ip + 2);
12748                                 CHECK_ARG (n);
12749                                 if (!dont_verify_stloc && target_type_is_incompatible (cfg, param_types [n], *sp))
12750                                         UNVERIFIED;
12751                                 EMIT_NEW_ARGSTORE (cfg, ins, n, *sp);
12752                                 ip += 4;
12753                                 break;
12754                         case CEE_LDLOC:
12755                                 CHECK_STACK_OVF (1);
12756                                 CHECK_OPSIZE (4);
12757                                 n = read16 (ip + 2);
12758                                 CHECK_LOCAL (n);
12759                                 EMIT_NEW_LOCLOAD (cfg, ins, n);
12760                                 *sp++ = ins;
12761                                 ip += 4;
12762                                 break;
12763                         case CEE_LDLOCA: {
12764                                 unsigned char *tmp_ip;
12765                                 CHECK_STACK_OVF (1);
12766                                 CHECK_OPSIZE (4);
12767                                 n = read16 (ip + 2);
12768                                 CHECK_LOCAL (n);
12769
12770                                 if ((tmp_ip = emit_optimized_ldloca_ir (cfg, ip, end, 2))) {
12771                                         ip = tmp_ip;
12772                                         inline_costs += 1;
12773                                         break;
12774                                 }                       
12775                                 
12776                                 EMIT_NEW_LOCLOADA (cfg, ins, n);
12777                                 *sp++ = ins;
12778                                 ip += 4;
12779                                 break;
12780                         }
12781                         case CEE_STLOC:
12782                                 CHECK_STACK (1);
12783                                 --sp;
12784                                 CHECK_OPSIZE (4);
12785                                 n = read16 (ip + 2);
12786                                 CHECK_LOCAL (n);
12787                                 if (!dont_verify_stloc && target_type_is_incompatible (cfg, header->locals [n], *sp))
12788                                         UNVERIFIED;
12789                                 emit_stloc_ir (cfg, sp, header, n);
12790                                 ip += 4;
12791                                 inline_costs += 1;
12792                                 break;
12793                         case CEE_LOCALLOC:
12794                                 CHECK_STACK (1);
12795                                 --sp;
12796                                 if (sp != stack_start) 
12797                                         UNVERIFIED;
12798                                 if (cfg->method != method) 
12799                                         /* 
12800                                          * Inlining this into a loop in a parent could lead to 
12801                                          * stack overflows which is different behavior than the
12802                                          * non-inlined case, thus disable inlining in this case.
12803                                          */
12804                                         INLINE_FAILURE("localloc");
12805
12806                                 MONO_INST_NEW (cfg, ins, OP_LOCALLOC);
12807                                 ins->dreg = alloc_preg (cfg);
12808                                 ins->sreg1 = sp [0]->dreg;
12809                                 ins->type = STACK_PTR;
12810                                 MONO_ADD_INS (cfg->cbb, ins);
12811
12812                                 cfg->flags |= MONO_CFG_HAS_ALLOCA;
12813                                 if (init_locals)
12814                                         ins->flags |= MONO_INST_INIT;
12815
12816                                 *sp++ = ins;
12817                                 ip += 2;
12818                                 break;
12819                         case CEE_ENDFILTER: {
12820                                 MonoExceptionClause *clause, *nearest;
12821                                 int cc;
12822
12823                                 CHECK_STACK (1);
12824                                 --sp;
12825                                 if ((sp != stack_start) || (sp [0]->type != STACK_I4)) 
12826                                         UNVERIFIED;
12827                                 MONO_INST_NEW (cfg, ins, OP_ENDFILTER);
12828                                 ins->sreg1 = (*sp)->dreg;
12829                                 MONO_ADD_INS (cfg->cbb, ins);
12830                                 start_new_bblock = 1;
12831                                 ip += 2;
12832
12833                                 nearest = NULL;
12834                                 for (cc = 0; cc < header->num_clauses; ++cc) {
12835                                         clause = &header->clauses [cc];
12836                                         if ((clause->flags & MONO_EXCEPTION_CLAUSE_FILTER) &&
12837                                                 ((ip - header->code) > clause->data.filter_offset && (ip - header->code) <= clause->handler_offset) &&
12838                                             (!nearest || (clause->data.filter_offset < nearest->data.filter_offset)))
12839                                                 nearest = clause;
12840                                 }
12841                                 g_assert (nearest);
12842                                 if ((ip - header->code) != nearest->handler_offset)
12843                                         UNVERIFIED;
12844
12845                                 break;
12846                         }
12847                         case CEE_UNALIGNED_:
12848                                 ins_flag |= MONO_INST_UNALIGNED;
12849                                 /* FIXME: record alignment? we can assume 1 for now */
12850                                 CHECK_OPSIZE (3);
12851                                 ip += 3;
12852                                 break;
12853                         case CEE_VOLATILE_:
12854                                 ins_flag |= MONO_INST_VOLATILE;
12855                                 ip += 2;
12856                                 break;
12857                         case CEE_TAIL_:
12858                                 ins_flag   |= MONO_INST_TAILCALL;
12859                                 cfg->flags |= MONO_CFG_HAS_TAIL;
12860                                 /* Can't inline tail calls at this time */
12861                                 inline_costs += 100000;
12862                                 ip += 2;
12863                                 break;
12864                         case CEE_INITOBJ:
12865                                 CHECK_STACK (1);
12866                                 --sp;
12867                                 CHECK_OPSIZE (6);
12868                                 token = read32 (ip + 2);
12869                                 klass = mini_get_class (method, token, generic_context);
12870                                 CHECK_TYPELOAD (klass);
12871                                 if (generic_class_is_reference_type (cfg, klass))
12872                                         MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STORE_MEMBASE_IMM, sp [0]->dreg, 0, 0);
12873                                 else
12874                                         mini_emit_initobj (cfg, *sp, NULL, klass);
12875                                 ip += 6;
12876                                 inline_costs += 1;
12877                                 break;
12878                         case CEE_CONSTRAINED_:
12879                                 CHECK_OPSIZE (6);
12880                                 token = read32 (ip + 2);
12881                                 constrained_class = mini_get_class (method, token, generic_context);
12882                                 CHECK_TYPELOAD (constrained_class);
12883                                 ip += 6;
12884                                 break;
12885                         case CEE_CPBLK:
12886                         case CEE_INITBLK: {
12887                                 MonoInst *iargs [3];
12888                                 CHECK_STACK (3);
12889                                 sp -= 3;
12890
12891                                 /* Skip optimized paths for volatile operations. */
12892                                 if ((ip [1] == CEE_CPBLK) && !(ins_flag & MONO_INST_VOLATILE) && (cfg->opt & MONO_OPT_INTRINS) && (sp [2]->opcode == OP_ICONST) && ((n = sp [2]->inst_c0) <= sizeof (gpointer) * 5)) {
12893                                         mini_emit_memcpy (cfg, sp [0]->dreg, 0, sp [1]->dreg, 0, sp [2]->inst_c0, 0);
12894                                 } else if ((ip [1] == CEE_INITBLK) && !(ins_flag & MONO_INST_VOLATILE) && (cfg->opt & MONO_OPT_INTRINS) && (sp [2]->opcode == OP_ICONST) && ((n = sp [2]->inst_c0) <= sizeof (gpointer) * 5) && (sp [1]->opcode == OP_ICONST) && (sp [1]->inst_c0 == 0)) {
12895                                         /* emit_memset only works when val == 0 */
12896                                         mini_emit_memset (cfg, sp [0]->dreg, 0, sp [2]->inst_c0, sp [1]->inst_c0, 0);
12897                                 } else {
12898                                         MonoInst *call;
12899                                         iargs [0] = sp [0];
12900                                         iargs [1] = sp [1];
12901                                         iargs [2] = sp [2];
12902                                         if (ip [1] == CEE_CPBLK) {
12903                                                 /*
12904                                                  * FIXME: It's unclear whether we should be emitting both the acquire
12905                                                  * and release barriers for cpblk. It is technically both a load and
12906                                                  * store operation, so it seems like that's the sensible thing to do.
12907                                                  *
12908                                                  * FIXME: We emit full barriers on both sides of the operation for
12909                                                  * simplicity. We should have a separate atomic memcpy method instead.
12910                                                  */
12911                                                 MonoMethod *memcpy_method = get_memcpy_method ();
12912
12913                                                 if (ins_flag & MONO_INST_VOLATILE)
12914                                                         emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_SEQ);
12915
12916                                                 call = mono_emit_method_call (cfg, memcpy_method, iargs, NULL);
12917                                                 call->flags |= ins_flag;
12918
12919                                                 if (ins_flag & MONO_INST_VOLATILE)
12920                                                         emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_SEQ);
12921                                         } else {
12922                                                 MonoMethod *memset_method = get_memset_method ();
12923                                                 if (ins_flag & MONO_INST_VOLATILE) {
12924                                                         /* Volatile stores have release semantics, see 12.6.7 in Ecma 335 */
12925                                                         emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL);
12926                                                 }
12927                                                 call = mono_emit_method_call (cfg, memset_method, iargs, NULL);
12928                                                 call->flags |= ins_flag;
12929                                         }
12930                                 }
12931                                 ip += 2;
12932                                 ins_flag = 0;
12933                                 inline_costs += 1;
12934                                 break;
12935                         }
12936                         case CEE_NO_:
12937                                 CHECK_OPSIZE (3);
12938                                 if (ip [2] & 0x1)
12939                                         ins_flag |= MONO_INST_NOTYPECHECK;
12940                                 if (ip [2] & 0x2)
12941                                         ins_flag |= MONO_INST_NORANGECHECK;
12942                                 /* we ignore the no-nullcheck for now since we
12943                                  * really do it explicitly only when doing callvirt->call
12944                                  */
12945                                 ip += 3;
12946                                 break;
12947                         case CEE_RETHROW: {
12948                                 MonoInst *load;
12949                                 int handler_offset = -1;
12950
12951                                 for (i = 0; i < header->num_clauses; ++i) {
12952                                         MonoExceptionClause *clause = &header->clauses [i];
12953                                         if (MONO_OFFSET_IN_HANDLER (clause, ip - header->code) && !(clause->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
12954                                                 handler_offset = clause->handler_offset;
12955                                                 break;
12956                                         }
12957                                 }
12958
12959                                 cfg->cbb->flags |= BB_EXCEPTION_UNSAFE;
12960
12961                                 if (handler_offset == -1)
12962                                         UNVERIFIED;
12963
12964                                 EMIT_NEW_TEMPLOAD (cfg, load, mono_find_exvar_for_offset (cfg, handler_offset)->inst_c0);
12965                                 MONO_INST_NEW (cfg, ins, OP_RETHROW);
12966                                 ins->sreg1 = load->dreg;
12967                                 MONO_ADD_INS (cfg->cbb, ins);
12968
12969                                 MONO_INST_NEW (cfg, ins, OP_NOT_REACHED);
12970                                 MONO_ADD_INS (cfg->cbb, ins);
12971
12972                                 sp = stack_start;
12973                                 link_bblock (cfg, cfg->cbb, end_bblock);
12974                                 start_new_bblock = 1;
12975                                 ip += 2;
12976                                 break;
12977                         }
12978                         case CEE_SIZEOF: {
12979                                 guint32 val;
12980                                 int ialign;
12981
12982                                 CHECK_STACK_OVF (1);
12983                                 CHECK_OPSIZE (6);
12984                                 token = read32 (ip + 2);
12985                                 if (mono_metadata_token_table (token) == MONO_TABLE_TYPESPEC && !image_is_dynamic (method->klass->image) && !generic_context) {
12986                                         MonoType *type = mono_type_create_from_typespec_checked (image, token, &cfg->error);
12987                                         CHECK_CFG_ERROR;
12988
12989                                         val = mono_type_size (type, &ialign);
12990                                 } else {
12991                                         MonoClass *klass = mini_get_class (method, token, generic_context);
12992                                         CHECK_TYPELOAD (klass);
12993
12994                                         val = mono_type_size (&klass->byval_arg, &ialign);
12995
12996                                         if (mini_is_gsharedvt_klass (klass))
12997                                                 GSHAREDVT_FAILURE (*ip);
12998                                 }
12999                                 EMIT_NEW_ICONST (cfg, ins, val);
13000                                 *sp++= ins;
13001                                 ip += 6;
13002                                 break;
13003                         }
13004                         case CEE_REFANYTYPE: {
13005                                 MonoInst *src_var, *src;
13006
13007                                 GSHAREDVT_FAILURE (*ip);
13008
13009                                 CHECK_STACK (1);
13010                                 --sp;
13011
13012                                 // FIXME:
13013                                 src_var = get_vreg_to_inst (cfg, sp [0]->dreg);
13014                                 if (!src_var)
13015                                         src_var = mono_compile_create_var_for_vreg (cfg, &mono_defaults.typed_reference_class->byval_arg, OP_LOCAL, sp [0]->dreg);
13016                                 EMIT_NEW_VARLOADA (cfg, src, src_var, src_var->inst_vtype);
13017                                 EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &mono_defaults.typehandle_class->byval_arg, src->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, type));
13018                                 *sp++ = ins;
13019                                 ip += 2;
13020                                 break;
13021                         }
13022                         case CEE_READONLY_:
13023                                 readonly = TRUE;
13024                                 ip += 2;
13025                                 break;
13026
13027                         case CEE_UNUSED56:
13028                         case CEE_UNUSED57:
13029                         case CEE_UNUSED70:
13030                         case CEE_UNUSED:
13031                         case CEE_UNUSED99:
13032                                 UNVERIFIED;
13033                                 
13034                         default:
13035                                 g_warning ("opcode 0xfe 0x%02x not handled", ip [1]);
13036                                 UNVERIFIED;
13037                         }
13038                         break;
13039                 }
13040                 case CEE_UNUSED58:
13041                 case CEE_UNUSED1:
13042                         UNVERIFIED;
13043
13044                 default:
13045                         g_warning ("opcode 0x%02x not handled", *ip);
13046                         UNVERIFIED;
13047                 }
13048         }
13049         if (start_new_bblock != 1)
13050                 UNVERIFIED;
13051
13052         cfg->cbb->cil_length = ip - cfg->cbb->cil_code;
13053         if (cfg->cbb->next_bb) {
13054                 /* This could already be set because of inlining, #693905 */
13055                 MonoBasicBlock *bb = cfg->cbb;
13056
13057                 while (bb->next_bb)
13058                         bb = bb->next_bb;
13059                 bb->next_bb = end_bblock;
13060         } else {
13061                 cfg->cbb->next_bb = end_bblock;
13062         }
13063
13064         if (cfg->method == method && cfg->domainvar) {
13065                 MonoInst *store;
13066                 MonoInst *get_domain;
13067
13068                 cfg->cbb = init_localsbb;
13069
13070                 if ((get_domain = mono_get_domain_intrinsic (cfg))) {
13071                         MONO_ADD_INS (cfg->cbb, get_domain);
13072                 } else {
13073                         get_domain = mono_emit_jit_icall (cfg, mono_domain_get, NULL);
13074                 }
13075                 NEW_TEMPSTORE (cfg, store, cfg->domainvar->inst_c0, get_domain);
13076                 MONO_ADD_INS (cfg->cbb, store);
13077         }
13078
13079 #if defined(TARGET_POWERPC) || defined(TARGET_X86)
13080         if (cfg->compile_aot)
13081                 /* FIXME: The plt slots require a GOT var even if the method doesn't use it */
13082                 mono_get_got_var (cfg);
13083 #endif
13084
13085         if (cfg->method == method && cfg->got_var)
13086                 mono_emit_load_got_addr (cfg);
13087
13088         if (init_localsbb) {
13089                 cfg->cbb = init_localsbb;
13090                 cfg->ip = NULL;
13091                 for (i = 0; i < header->num_locals; ++i) {
13092                         emit_init_local (cfg, i, header->locals [i], init_locals);
13093                 }
13094         }
13095
13096         if (cfg->init_ref_vars && cfg->method == method) {
13097                 /* Emit initialization for ref vars */
13098                 // FIXME: Avoid duplication initialization for IL locals.
13099                 for (i = 0; i < cfg->num_varinfo; ++i) {
13100                         MonoInst *ins = cfg->varinfo [i];
13101
13102                         if (ins->opcode == OP_LOCAL && ins->type == STACK_OBJ)
13103                                 MONO_EMIT_NEW_PCONST (cfg, ins->dreg, NULL);
13104                 }
13105         }
13106
13107         if (cfg->lmf_var && cfg->method == method && !cfg->llvm_only) {
13108                 cfg->cbb = init_localsbb;
13109                 emit_push_lmf (cfg);
13110         }
13111
13112         cfg->cbb = init_localsbb;
13113         emit_instrumentation_call (cfg, mono_profiler_method_enter);
13114
13115         if (seq_points) {
13116                 MonoBasicBlock *bb;
13117
13118                 /*
13119                  * Make seq points at backward branch targets interruptable.
13120                  */
13121                 for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
13122                         if (bb->code && bb->in_count > 1 && bb->code->opcode == OP_SEQ_POINT)
13123                                 bb->code->flags |= MONO_INST_SINGLE_STEP_LOC;
13124         }
13125
13126         /* Add a sequence point for method entry/exit events */
13127         if (seq_points && cfg->gen_sdb_seq_points) {
13128                 NEW_SEQ_POINT (cfg, ins, METHOD_ENTRY_IL_OFFSET, FALSE);
13129                 MONO_ADD_INS (init_localsbb, ins);
13130                 NEW_SEQ_POINT (cfg, ins, METHOD_EXIT_IL_OFFSET, FALSE);
13131                 MONO_ADD_INS (cfg->bb_exit, ins);
13132         }
13133
13134         /*
13135          * Add seq points for IL offsets which have line number info, but wasn't generated a seq point during JITting because
13136          * the code they refer to was dead (#11880).
13137          */
13138         if (sym_seq_points) {
13139                 for (i = 0; i < header->code_size; ++i) {
13140                         if (mono_bitset_test_fast (seq_point_locs, i) && !mono_bitset_test_fast (seq_point_set_locs, i)) {
13141                                 MonoInst *ins;
13142
13143                                 NEW_SEQ_POINT (cfg, ins, i, FALSE);
13144                                 mono_add_seq_point (cfg, NULL, ins, SEQ_POINT_NATIVE_OFFSET_DEAD_CODE);
13145                         }
13146                 }
13147         }
13148
13149         cfg->ip = NULL;
13150
13151         if (cfg->method == method) {
13152                 MonoBasicBlock *bb;
13153                 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
13154                         bb->region = mono_find_block_region (cfg, bb->real_offset);
13155                         if (cfg->spvars)
13156                                 mono_create_spvar_for_region (cfg, bb->region);
13157                         if (cfg->verbose_level > 2)
13158                                 printf ("REGION BB%d IL_%04x ID_%08X\n", bb->block_num, bb->real_offset, bb->region);
13159                 }
13160         }
13161
13162         if (inline_costs < 0) {
13163                 char *mname;
13164
13165                 /* Method is too large */
13166                 mname = mono_method_full_name (method, TRUE);
13167                 mono_cfg_set_exception (cfg, MONO_EXCEPTION_INVALID_PROGRAM);
13168                 cfg->exception_message = g_strdup_printf ("Method %s is too complex.", mname);
13169                 g_free (mname);
13170         }
13171
13172         if ((cfg->verbose_level > 2) && (cfg->method == method)) 
13173                 mono_print_code (cfg, "AFTER METHOD-TO-IR");
13174
13175         goto cleanup;
13176
13177 mono_error_exit:
13178         g_assert (!mono_error_ok (&cfg->error));
13179         goto cleanup;
13180  
13181  exception_exit:
13182         g_assert (cfg->exception_type != MONO_EXCEPTION_NONE);
13183         goto cleanup;
13184
13185  unverified:
13186         set_exception_type_from_invalid_il (cfg, method, ip);
13187         goto cleanup;
13188
13189  cleanup:
13190         g_slist_free (class_inits);
13191         mono_basic_block_free (original_bb);
13192         cfg->dont_inline = g_list_remove (cfg->dont_inline, method);
13193         cfg->headers_to_free = g_slist_prepend_mempool (cfg->mempool, cfg->headers_to_free, header);
13194         if (cfg->exception_type)
13195                 return -1;
13196         else
13197                 return inline_costs;
13198 }
13199
13200 static int
13201 store_membase_reg_to_store_membase_imm (int opcode)
13202 {
13203         switch (opcode) {
13204         case OP_STORE_MEMBASE_REG:
13205                 return OP_STORE_MEMBASE_IMM;
13206         case OP_STOREI1_MEMBASE_REG:
13207                 return OP_STOREI1_MEMBASE_IMM;
13208         case OP_STOREI2_MEMBASE_REG:
13209                 return OP_STOREI2_MEMBASE_IMM;
13210         case OP_STOREI4_MEMBASE_REG:
13211                 return OP_STOREI4_MEMBASE_IMM;
13212         case OP_STOREI8_MEMBASE_REG:
13213                 return OP_STOREI8_MEMBASE_IMM;
13214         default:
13215                 g_assert_not_reached ();
13216         }
13217
13218         return -1;
13219 }               
13220
13221 int
13222 mono_op_to_op_imm (int opcode)
13223 {
13224         switch (opcode) {
13225         case OP_IADD:
13226                 return OP_IADD_IMM;
13227         case OP_ISUB:
13228                 return OP_ISUB_IMM;
13229         case OP_IDIV:
13230                 return OP_IDIV_IMM;
13231         case OP_IDIV_UN:
13232                 return OP_IDIV_UN_IMM;
13233         case OP_IREM:
13234                 return OP_IREM_IMM;
13235         case OP_IREM_UN:
13236                 return OP_IREM_UN_IMM;
13237         case OP_IMUL:
13238                 return OP_IMUL_IMM;
13239         case OP_IAND:
13240                 return OP_IAND_IMM;
13241         case OP_IOR:
13242                 return OP_IOR_IMM;
13243         case OP_IXOR:
13244                 return OP_IXOR_IMM;
13245         case OP_ISHL:
13246                 return OP_ISHL_IMM;
13247         case OP_ISHR:
13248                 return OP_ISHR_IMM;
13249         case OP_ISHR_UN:
13250                 return OP_ISHR_UN_IMM;
13251
13252         case OP_LADD:
13253                 return OP_LADD_IMM;
13254         case OP_LSUB:
13255                 return OP_LSUB_IMM;
13256         case OP_LAND:
13257                 return OP_LAND_IMM;
13258         case OP_LOR:
13259                 return OP_LOR_IMM;
13260         case OP_LXOR:
13261                 return OP_LXOR_IMM;
13262         case OP_LSHL:
13263                 return OP_LSHL_IMM;
13264         case OP_LSHR:
13265                 return OP_LSHR_IMM;
13266         case OP_LSHR_UN:
13267                 return OP_LSHR_UN_IMM;
13268 #if SIZEOF_REGISTER == 8
13269         case OP_LREM:
13270                 return OP_LREM_IMM;
13271 #endif
13272
13273         case OP_COMPARE:
13274                 return OP_COMPARE_IMM;
13275         case OP_ICOMPARE:
13276                 return OP_ICOMPARE_IMM;
13277         case OP_LCOMPARE:
13278                 return OP_LCOMPARE_IMM;
13279
13280         case OP_STORE_MEMBASE_REG:
13281                 return OP_STORE_MEMBASE_IMM;
13282         case OP_STOREI1_MEMBASE_REG:
13283                 return OP_STOREI1_MEMBASE_IMM;
13284         case OP_STOREI2_MEMBASE_REG:
13285                 return OP_STOREI2_MEMBASE_IMM;
13286         case OP_STOREI4_MEMBASE_REG:
13287                 return OP_STOREI4_MEMBASE_IMM;
13288
13289 #if defined(TARGET_X86) || defined (TARGET_AMD64)
13290         case OP_X86_PUSH:
13291                 return OP_X86_PUSH_IMM;
13292         case OP_X86_COMPARE_MEMBASE_REG:
13293                 return OP_X86_COMPARE_MEMBASE_IMM;
13294 #endif
13295 #if defined(TARGET_AMD64)
13296         case OP_AMD64_ICOMPARE_MEMBASE_REG:
13297                 return OP_AMD64_ICOMPARE_MEMBASE_IMM;
13298 #endif
13299         case OP_VOIDCALL_REG:
13300                 return OP_VOIDCALL;
13301         case OP_CALL_REG:
13302                 return OP_CALL;
13303         case OP_LCALL_REG:
13304                 return OP_LCALL;
13305         case OP_FCALL_REG:
13306                 return OP_FCALL;
13307         case OP_LOCALLOC:
13308                 return OP_LOCALLOC_IMM;
13309         }
13310
13311         return -1;
13312 }
13313
13314 static int
13315 ldind_to_load_membase (int opcode)
13316 {
13317         switch (opcode) {
13318         case CEE_LDIND_I1:
13319                 return OP_LOADI1_MEMBASE;
13320         case CEE_LDIND_U1:
13321                 return OP_LOADU1_MEMBASE;
13322         case CEE_LDIND_I2:
13323                 return OP_LOADI2_MEMBASE;
13324         case CEE_LDIND_U2:
13325                 return OP_LOADU2_MEMBASE;
13326         case CEE_LDIND_I4:
13327                 return OP_LOADI4_MEMBASE;
13328         case CEE_LDIND_U4:
13329                 return OP_LOADU4_MEMBASE;
13330         case CEE_LDIND_I:
13331                 return OP_LOAD_MEMBASE;
13332         case CEE_LDIND_REF:
13333                 return OP_LOAD_MEMBASE;
13334         case CEE_LDIND_I8:
13335                 return OP_LOADI8_MEMBASE;
13336         case CEE_LDIND_R4:
13337                 return OP_LOADR4_MEMBASE;
13338         case CEE_LDIND_R8:
13339                 return OP_LOADR8_MEMBASE;
13340         default:
13341                 g_assert_not_reached ();
13342         }
13343
13344         return -1;
13345 }
13346
13347 static int
13348 stind_to_store_membase (int opcode)
13349 {
13350         switch (opcode) {
13351         case CEE_STIND_I1:
13352                 return OP_STOREI1_MEMBASE_REG;
13353         case CEE_STIND_I2:
13354                 return OP_STOREI2_MEMBASE_REG;
13355         case CEE_STIND_I4:
13356                 return OP_STOREI4_MEMBASE_REG;
13357         case CEE_STIND_I:
13358         case CEE_STIND_REF:
13359                 return OP_STORE_MEMBASE_REG;
13360         case CEE_STIND_I8:
13361                 return OP_STOREI8_MEMBASE_REG;
13362         case CEE_STIND_R4:
13363                 return OP_STORER4_MEMBASE_REG;
13364         case CEE_STIND_R8:
13365                 return OP_STORER8_MEMBASE_REG;
13366         default:
13367                 g_assert_not_reached ();
13368         }
13369
13370         return -1;
13371 }
13372
13373 int
13374 mono_load_membase_to_load_mem (int opcode)
13375 {
13376         // FIXME: Add a MONO_ARCH_HAVE_LOAD_MEM macro
13377 #if defined(TARGET_X86) || defined(TARGET_AMD64)
13378         switch (opcode) {
13379         case OP_LOAD_MEMBASE:
13380                 return OP_LOAD_MEM;
13381         case OP_LOADU1_MEMBASE:
13382                 return OP_LOADU1_MEM;
13383         case OP_LOADU2_MEMBASE:
13384                 return OP_LOADU2_MEM;
13385         case OP_LOADI4_MEMBASE:
13386                 return OP_LOADI4_MEM;
13387         case OP_LOADU4_MEMBASE:
13388                 return OP_LOADU4_MEM;
13389 #if SIZEOF_REGISTER == 8
13390         case OP_LOADI8_MEMBASE:
13391                 return OP_LOADI8_MEM;
13392 #endif
13393         }
13394 #endif
13395
13396         return -1;
13397 }
13398
13399 static inline int
13400 op_to_op_dest_membase (int store_opcode, int opcode)
13401 {
13402 #if defined(TARGET_X86)
13403         if (!((store_opcode == OP_STORE_MEMBASE_REG) || (store_opcode == OP_STOREI4_MEMBASE_REG)))
13404                 return -1;
13405
13406         switch (opcode) {
13407         case OP_IADD:
13408                 return OP_X86_ADD_MEMBASE_REG;
13409         case OP_ISUB:
13410                 return OP_X86_SUB_MEMBASE_REG;
13411         case OP_IAND:
13412                 return OP_X86_AND_MEMBASE_REG;
13413         case OP_IOR:
13414                 return OP_X86_OR_MEMBASE_REG;
13415         case OP_IXOR:
13416                 return OP_X86_XOR_MEMBASE_REG;
13417         case OP_ADD_IMM:
13418         case OP_IADD_IMM:
13419                 return OP_X86_ADD_MEMBASE_IMM;
13420         case OP_SUB_IMM:
13421         case OP_ISUB_IMM:
13422                 return OP_X86_SUB_MEMBASE_IMM;
13423         case OP_AND_IMM:
13424         case OP_IAND_IMM:
13425                 return OP_X86_AND_MEMBASE_IMM;
13426         case OP_OR_IMM:
13427         case OP_IOR_IMM:
13428                 return OP_X86_OR_MEMBASE_IMM;
13429         case OP_XOR_IMM:
13430         case OP_IXOR_IMM:
13431                 return OP_X86_XOR_MEMBASE_IMM;
13432         case OP_MOVE:
13433                 return OP_NOP;
13434         }
13435 #endif
13436
13437 #if defined(TARGET_AMD64)
13438         if (!((store_opcode == OP_STORE_MEMBASE_REG) || (store_opcode == OP_STOREI4_MEMBASE_REG) || (store_opcode == OP_STOREI8_MEMBASE_REG)))
13439                 return -1;
13440
13441         switch (opcode) {
13442         case OP_IADD:
13443                 return OP_X86_ADD_MEMBASE_REG;
13444         case OP_ISUB:
13445                 return OP_X86_SUB_MEMBASE_REG;
13446         case OP_IAND:
13447                 return OP_X86_AND_MEMBASE_REG;
13448         case OP_IOR:
13449                 return OP_X86_OR_MEMBASE_REG;
13450         case OP_IXOR:
13451                 return OP_X86_XOR_MEMBASE_REG;
13452         case OP_IADD_IMM:
13453                 return OP_X86_ADD_MEMBASE_IMM;
13454         case OP_ISUB_IMM:
13455                 return OP_X86_SUB_MEMBASE_IMM;
13456         case OP_IAND_IMM:
13457                 return OP_X86_AND_MEMBASE_IMM;
13458         case OP_IOR_IMM:
13459                 return OP_X86_OR_MEMBASE_IMM;
13460         case OP_IXOR_IMM:
13461                 return OP_X86_XOR_MEMBASE_IMM;
13462         case OP_LADD:
13463                 return OP_AMD64_ADD_MEMBASE_REG;
13464         case OP_LSUB:
13465                 return OP_AMD64_SUB_MEMBASE_REG;
13466         case OP_LAND:
13467                 return OP_AMD64_AND_MEMBASE_REG;
13468         case OP_LOR:
13469                 return OP_AMD64_OR_MEMBASE_REG;
13470         case OP_LXOR:
13471                 return OP_AMD64_XOR_MEMBASE_REG;
13472         case OP_ADD_IMM:
13473         case OP_LADD_IMM:
13474                 return OP_AMD64_ADD_MEMBASE_IMM;
13475         case OP_SUB_IMM:
13476         case OP_LSUB_IMM:
13477                 return OP_AMD64_SUB_MEMBASE_IMM;
13478         case OP_AND_IMM:
13479         case OP_LAND_IMM:
13480                 return OP_AMD64_AND_MEMBASE_IMM;
13481         case OP_OR_IMM:
13482         case OP_LOR_IMM:
13483                 return OP_AMD64_OR_MEMBASE_IMM;
13484         case OP_XOR_IMM:
13485         case OP_LXOR_IMM:
13486                 return OP_AMD64_XOR_MEMBASE_IMM;
13487         case OP_MOVE:
13488                 return OP_NOP;
13489         }
13490 #endif
13491
13492         return -1;
13493 }
13494
13495 static inline int
13496 op_to_op_store_membase (int store_opcode, int opcode)
13497 {
13498 #if defined(TARGET_X86) || defined(TARGET_AMD64)
13499         switch (opcode) {
13500         case OP_ICEQ:
13501                 if (store_opcode == OP_STOREI1_MEMBASE_REG)
13502                         return OP_X86_SETEQ_MEMBASE;
13503         case OP_CNE:
13504                 if (store_opcode == OP_STOREI1_MEMBASE_REG)
13505                         return OP_X86_SETNE_MEMBASE;
13506         }
13507 #endif
13508
13509         return -1;
13510 }
13511
13512 static inline int
13513 op_to_op_src1_membase (MonoCompile *cfg, int load_opcode, int opcode)
13514 {
13515 #ifdef TARGET_X86
13516         /* FIXME: This has sign extension issues */
13517         /*
13518         if ((opcode == OP_ICOMPARE_IMM) && (load_opcode == OP_LOADU1_MEMBASE))
13519                 return OP_X86_COMPARE_MEMBASE8_IMM;
13520         */
13521
13522         if (!((load_opcode == OP_LOAD_MEMBASE) || (load_opcode == OP_LOADI4_MEMBASE) || (load_opcode == OP_LOADU4_MEMBASE)))
13523                 return -1;
13524
13525         switch (opcode) {
13526         case OP_X86_PUSH:
13527                 return OP_X86_PUSH_MEMBASE;
13528         case OP_COMPARE_IMM:
13529         case OP_ICOMPARE_IMM:
13530                 return OP_X86_COMPARE_MEMBASE_IMM;
13531         case OP_COMPARE:
13532         case OP_ICOMPARE:
13533                 return OP_X86_COMPARE_MEMBASE_REG;
13534         }
13535 #endif
13536
13537 #ifdef TARGET_AMD64
13538         /* FIXME: This has sign extension issues */
13539         /*
13540         if ((opcode == OP_ICOMPARE_IMM) && (load_opcode == OP_LOADU1_MEMBASE))
13541                 return OP_X86_COMPARE_MEMBASE8_IMM;
13542         */
13543
13544         switch (opcode) {
13545         case OP_X86_PUSH:
13546                 if ((load_opcode == OP_LOAD_MEMBASE && !cfg->backend->ilp32) || (load_opcode == OP_LOADI8_MEMBASE))
13547                         return OP_X86_PUSH_MEMBASE;
13548                 break;
13549                 /* FIXME: This only works for 32 bit immediates
13550         case OP_COMPARE_IMM:
13551         case OP_LCOMPARE_IMM:
13552                 if ((load_opcode == OP_LOAD_MEMBASE) || (load_opcode == OP_LOADI8_MEMBASE))
13553                         return OP_AMD64_COMPARE_MEMBASE_IMM;
13554                 */
13555         case OP_ICOMPARE_IMM:
13556                 if ((load_opcode == OP_LOADI4_MEMBASE) || (load_opcode == OP_LOADU4_MEMBASE))
13557                         return OP_AMD64_ICOMPARE_MEMBASE_IMM;
13558                 break;
13559         case OP_COMPARE:
13560         case OP_LCOMPARE:
13561                 if (cfg->backend->ilp32 && load_opcode == OP_LOAD_MEMBASE)
13562                         return OP_AMD64_ICOMPARE_MEMBASE_REG;
13563                 if ((load_opcode == OP_LOAD_MEMBASE && !cfg->backend->ilp32) || (load_opcode == OP_LOADI8_MEMBASE))
13564                         return OP_AMD64_COMPARE_MEMBASE_REG;
13565                 break;
13566         case OP_ICOMPARE:
13567                 if ((load_opcode == OP_LOADI4_MEMBASE) || (load_opcode == OP_LOADU4_MEMBASE))
13568                         return OP_AMD64_ICOMPARE_MEMBASE_REG;
13569                 break;
13570         }
13571 #endif
13572
13573         return -1;
13574 }
13575
13576 static inline int
13577 op_to_op_src2_membase (MonoCompile *cfg, int load_opcode, int opcode)
13578 {
13579 #ifdef TARGET_X86
13580         if (!((load_opcode == OP_LOAD_MEMBASE) || (load_opcode == OP_LOADI4_MEMBASE) || (load_opcode == OP_LOADU4_MEMBASE)))
13581                 return -1;
13582         
13583         switch (opcode) {
13584         case OP_COMPARE:
13585         case OP_ICOMPARE:
13586                 return OP_X86_COMPARE_REG_MEMBASE;
13587         case OP_IADD:
13588                 return OP_X86_ADD_REG_MEMBASE;
13589         case OP_ISUB:
13590                 return OP_X86_SUB_REG_MEMBASE;
13591         case OP_IAND:
13592                 return OP_X86_AND_REG_MEMBASE;
13593         case OP_IOR:
13594                 return OP_X86_OR_REG_MEMBASE;
13595         case OP_IXOR:
13596                 return OP_X86_XOR_REG_MEMBASE;
13597         }
13598 #endif
13599
13600 #ifdef TARGET_AMD64
13601         if ((load_opcode == OP_LOADI4_MEMBASE) || (load_opcode == OP_LOADU4_MEMBASE) || (load_opcode == OP_LOAD_MEMBASE && cfg->backend->ilp32)) {
13602                 switch (opcode) {
13603                 case OP_ICOMPARE:
13604                         return OP_AMD64_ICOMPARE_REG_MEMBASE;
13605                 case OP_IADD:
13606                         return OP_X86_ADD_REG_MEMBASE;
13607                 case OP_ISUB:
13608                         return OP_X86_SUB_REG_MEMBASE;
13609                 case OP_IAND:
13610                         return OP_X86_AND_REG_MEMBASE;
13611                 case OP_IOR:
13612                         return OP_X86_OR_REG_MEMBASE;
13613                 case OP_IXOR:
13614                         return OP_X86_XOR_REG_MEMBASE;
13615                 }
13616         } else if ((load_opcode == OP_LOADI8_MEMBASE) || (load_opcode == OP_LOAD_MEMBASE && !cfg->backend->ilp32)) {
13617                 switch (opcode) {
13618                 case OP_COMPARE:
13619                 case OP_LCOMPARE:
13620                         return OP_AMD64_COMPARE_REG_MEMBASE;
13621                 case OP_LADD:
13622                         return OP_AMD64_ADD_REG_MEMBASE;
13623                 case OP_LSUB:
13624                         return OP_AMD64_SUB_REG_MEMBASE;
13625                 case OP_LAND:
13626                         return OP_AMD64_AND_REG_MEMBASE;
13627                 case OP_LOR:
13628                         return OP_AMD64_OR_REG_MEMBASE;
13629                 case OP_LXOR:
13630                         return OP_AMD64_XOR_REG_MEMBASE;
13631                 }
13632         }
13633 #endif
13634
13635         return -1;
13636 }
13637
13638 int
13639 mono_op_to_op_imm_noemul (int opcode)
13640 {
13641         switch (opcode) {
13642 #if SIZEOF_REGISTER == 4 && !defined(MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS)
13643         case OP_LSHR:
13644         case OP_LSHL:
13645         case OP_LSHR_UN:
13646                 return -1;
13647 #endif
13648 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV)
13649         case OP_IDIV:
13650         case OP_IDIV_UN:
13651         case OP_IREM:
13652         case OP_IREM_UN:
13653                 return -1;
13654 #endif
13655 #if defined(MONO_ARCH_EMULATE_MUL_DIV)
13656         case OP_IMUL:
13657                 return -1;
13658 #endif
13659         default:
13660                 return mono_op_to_op_imm (opcode);
13661         }
13662 }
13663
13664 /**
13665  * mono_handle_global_vregs:
13666  *
13667  *   Make vregs used in more than one bblock 'global', i.e. allocate a variable
13668  * for them.
13669  */
13670 void
13671 mono_handle_global_vregs (MonoCompile *cfg)
13672 {
13673         gint32 *vreg_to_bb;
13674         MonoBasicBlock *bb;
13675         int i, pos;
13676
13677         vreg_to_bb = mono_mempool_alloc0 (cfg->mempool, sizeof (gint32*) * cfg->next_vreg + 1);
13678
13679 #ifdef MONO_ARCH_SIMD_INTRINSICS
13680         if (cfg->uses_simd_intrinsics)
13681                 mono_simd_simplify_indirection (cfg);
13682 #endif
13683
13684         /* Find local vregs used in more than one bb */
13685         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
13686                 MonoInst *ins = bb->code;       
13687                 int block_num = bb->block_num;
13688
13689                 if (cfg->verbose_level > 2)
13690                         printf ("\nHANDLE-GLOBAL-VREGS BLOCK %d:\n", bb->block_num);
13691
13692                 cfg->cbb = bb;
13693                 for (; ins; ins = ins->next) {
13694                         const char *spec = INS_INFO (ins->opcode);
13695                         int regtype = 0, regindex;
13696                         gint32 prev_bb;
13697
13698                         if (G_UNLIKELY (cfg->verbose_level > 2))
13699                                 mono_print_ins (ins);
13700
13701                         g_assert (ins->opcode >= MONO_CEE_LAST);
13702
13703                         for (regindex = 0; regindex < 4; regindex ++) {
13704                                 int vreg = 0;
13705
13706                                 if (regindex == 0) {
13707                                         regtype = spec [MONO_INST_DEST];
13708                                         if (regtype == ' ')
13709                                                 continue;
13710                                         vreg = ins->dreg;
13711                                 } else if (regindex == 1) {
13712                                         regtype = spec [MONO_INST_SRC1];
13713                                         if (regtype == ' ')
13714                                                 continue;
13715                                         vreg = ins->sreg1;
13716                                 } else if (regindex == 2) {
13717                                         regtype = spec [MONO_INST_SRC2];
13718                                         if (regtype == ' ')
13719                                                 continue;
13720                                         vreg = ins->sreg2;
13721                                 } else if (regindex == 3) {
13722                                         regtype = spec [MONO_INST_SRC3];
13723                                         if (regtype == ' ')
13724                                                 continue;
13725                                         vreg = ins->sreg3;
13726                                 }
13727
13728 #if SIZEOF_REGISTER == 4
13729                                 /* In the LLVM case, the long opcodes are not decomposed */
13730                                 if (regtype == 'l' && !COMPILE_LLVM (cfg)) {
13731                                         /*
13732                                          * Since some instructions reference the original long vreg,
13733                                          * and some reference the two component vregs, it is quite hard
13734                                          * to determine when it needs to be global. So be conservative.
13735                                          */
13736                                         if (!get_vreg_to_inst (cfg, vreg)) {
13737                                                 mono_compile_create_var_for_vreg (cfg, &mono_defaults.int64_class->byval_arg, OP_LOCAL, vreg);
13738
13739                                                 if (cfg->verbose_level > 2)
13740                                                         printf ("LONG VREG R%d made global.\n", vreg);
13741                                         }
13742
13743                                         /*
13744                                          * Make the component vregs volatile since the optimizations can
13745                                          * get confused otherwise.
13746                                          */
13747                                         get_vreg_to_inst (cfg, vreg + 1)->flags |= MONO_INST_VOLATILE;
13748                                         get_vreg_to_inst (cfg, vreg + 2)->flags |= MONO_INST_VOLATILE;
13749                                 }
13750 #endif
13751
13752                                 g_assert (vreg != -1);
13753
13754                                 prev_bb = vreg_to_bb [vreg];
13755                                 if (prev_bb == 0) {
13756                                         /* 0 is a valid block num */
13757                                         vreg_to_bb [vreg] = block_num + 1;
13758                                 } else if ((prev_bb != block_num + 1) && (prev_bb != -1)) {
13759                                         if (((regtype == 'i' && (vreg < MONO_MAX_IREGS))) || (regtype == 'f' && (vreg < MONO_MAX_FREGS)))
13760                                                 continue;
13761
13762                                         if (!get_vreg_to_inst (cfg, vreg)) {
13763                                                 if (G_UNLIKELY (cfg->verbose_level > 2))
13764                                                         printf ("VREG R%d used in BB%d and BB%d made global.\n", vreg, vreg_to_bb [vreg], block_num);
13765
13766                                                 switch (regtype) {
13767                                                 case 'i':
13768                                                         if (vreg_is_ref (cfg, vreg))
13769                                                                 mono_compile_create_var_for_vreg (cfg, &mono_defaults.object_class->byval_arg, OP_LOCAL, vreg);
13770                                                         else
13771                                                                 mono_compile_create_var_for_vreg (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL, vreg);
13772                                                         break;
13773                                                 case 'l':
13774                                                         mono_compile_create_var_for_vreg (cfg, &mono_defaults.int64_class->byval_arg, OP_LOCAL, vreg);
13775                                                         break;
13776                                                 case 'f':
13777                                                         mono_compile_create_var_for_vreg (cfg, &mono_defaults.double_class->byval_arg, OP_LOCAL, vreg);
13778                                                         break;
13779                                                 case 'v':
13780                                                         mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, vreg);
13781                                                         break;
13782                                                 default:
13783                                                         g_assert_not_reached ();
13784                                                 }
13785                                         }
13786
13787                                         /* Flag as having been used in more than one bb */
13788                                         vreg_to_bb [vreg] = -1;
13789                                 }
13790                         }
13791                 }
13792         }
13793
13794         /* If a variable is used in only one bblock, convert it into a local vreg */
13795         for (i = 0; i < cfg->num_varinfo; i++) {
13796                 MonoInst *var = cfg->varinfo [i];
13797                 MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
13798
13799                 switch (var->type) {
13800                 case STACK_I4:
13801                 case STACK_OBJ:
13802                 case STACK_PTR:
13803                 case STACK_MP:
13804                 case STACK_VTYPE:
13805 #if SIZEOF_REGISTER == 8
13806                 case STACK_I8:
13807 #endif
13808 #if !defined(TARGET_X86)
13809                 /* Enabling this screws up the fp stack on x86 */
13810                 case STACK_R8:
13811 #endif
13812                         if (mono_arch_is_soft_float ())
13813                                 break;
13814
13815                         /* Arguments are implicitly global */
13816                         /* Putting R4 vars into registers doesn't work currently */
13817                         /* The gsharedvt vars are implicitly referenced by ldaddr opcodes, but those opcodes are only generated later */
13818                         if ((var->opcode != OP_ARG) && (var != cfg->ret) && !(var->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)) && (vreg_to_bb [var->dreg] != -1) && (var->klass->byval_arg.type != MONO_TYPE_R4) && !cfg->disable_vreg_to_lvreg && var != cfg->gsharedvt_info_var && var != cfg->gsharedvt_locals_var && var != cfg->lmf_addr_var) {
13819                                 /* 
13820                                  * Make that the variable's liveness interval doesn't contain a call, since
13821                                  * that would cause the lvreg to be spilled, making the whole optimization
13822                                  * useless.
13823                                  */
13824                                 /* This is too slow for JIT compilation */
13825 #if 0
13826                                 if (cfg->compile_aot && vreg_to_bb [var->dreg]) {
13827                                         MonoInst *ins;
13828                                         int def_index, call_index, ins_index;
13829                                         gboolean spilled = FALSE;
13830
13831                                         def_index = -1;
13832                                         call_index = -1;
13833                                         ins_index = 0;
13834                                         for (ins = vreg_to_bb [var->dreg]->code; ins; ins = ins->next) {
13835                                                 const char *spec = INS_INFO (ins->opcode);
13836
13837                                                 if ((spec [MONO_INST_DEST] != ' ') && (ins->dreg == var->dreg))
13838                                                         def_index = ins_index;
13839
13840                                                 if (((spec [MONO_INST_SRC1] != ' ') && (ins->sreg1 == var->dreg)) ||
13841                                                         ((spec [MONO_INST_SRC1] != ' ') && (ins->sreg1 == var->dreg))) {
13842                                                         if (call_index > def_index) {
13843                                                                 spilled = TRUE;
13844                                                                 break;
13845                                                         }
13846                                                 }
13847
13848                                                 if (MONO_IS_CALL (ins))
13849                                                         call_index = ins_index;
13850
13851                                                 ins_index ++;
13852                                         }
13853
13854                                         if (spilled)
13855                                                 break;
13856                                 }
13857 #endif
13858
13859                                 if (G_UNLIKELY (cfg->verbose_level > 2))
13860                                         printf ("CONVERTED R%d(%d) TO VREG.\n", var->dreg, vmv->idx);
13861                                 var->flags |= MONO_INST_IS_DEAD;
13862                                 cfg->vreg_to_inst [var->dreg] = NULL;
13863                         }
13864                         break;
13865                 }
13866         }
13867
13868         /* 
13869          * Compress the varinfo and vars tables so the liveness computation is faster and
13870          * takes up less space.
13871          */
13872         pos = 0;
13873         for (i = 0; i < cfg->num_varinfo; ++i) {
13874                 MonoInst *var = cfg->varinfo [i];
13875                 if (pos < i && cfg->locals_start == i)
13876                         cfg->locals_start = pos;
13877                 if (!(var->flags & MONO_INST_IS_DEAD)) {
13878                         if (pos < i) {
13879                                 cfg->varinfo [pos] = cfg->varinfo [i];
13880                                 cfg->varinfo [pos]->inst_c0 = pos;
13881                                 memcpy (&cfg->vars [pos], &cfg->vars [i], sizeof (MonoMethodVar));
13882                                 cfg->vars [pos].idx = pos;
13883 #if SIZEOF_REGISTER == 4
13884                                 if (cfg->varinfo [pos]->type == STACK_I8) {
13885                                         /* Modify the two component vars too */
13886                                         MonoInst *var1;
13887
13888                                         var1 = get_vreg_to_inst (cfg, cfg->varinfo [pos]->dreg + 1);
13889                                         var1->inst_c0 = pos;
13890                                         var1 = get_vreg_to_inst (cfg, cfg->varinfo [pos]->dreg + 2);
13891                                         var1->inst_c0 = pos;
13892                                 }
13893 #endif
13894                         }
13895                         pos ++;
13896                 }
13897         }
13898         cfg->num_varinfo = pos;
13899         if (cfg->locals_start > cfg->num_varinfo)
13900                 cfg->locals_start = cfg->num_varinfo;
13901 }
13902
13903 /**
13904  * mono_spill_global_vars:
13905  *
13906  *   Generate spill code for variables which are not allocated to registers, 
13907  * and replace vregs with their allocated hregs. *need_local_opts is set to TRUE if
13908  * code is generated which could be optimized by the local optimization passes.
13909  */
13910 void
13911 mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts)
13912 {
13913         MonoBasicBlock *bb;
13914         char spec2 [16];
13915         int orig_next_vreg;
13916         guint32 *vreg_to_lvreg;
13917         guint32 *lvregs;
13918         guint32 i, lvregs_len;
13919         gboolean dest_has_lvreg = FALSE;
13920         guint32 stacktypes [128];
13921         MonoInst **live_range_start, **live_range_end;
13922         MonoBasicBlock **live_range_start_bb, **live_range_end_bb;
13923         int *gsharedvt_vreg_to_idx = NULL;
13924
13925         *need_local_opts = FALSE;
13926
13927         memset (spec2, 0, sizeof (spec2));
13928
13929         /* FIXME: Move this function to mini.c */
13930         stacktypes ['i'] = STACK_PTR;
13931         stacktypes ['l'] = STACK_I8;
13932         stacktypes ['f'] = STACK_R8;
13933 #ifdef MONO_ARCH_SIMD_INTRINSICS
13934         stacktypes ['x'] = STACK_VTYPE;
13935 #endif
13936
13937 #if SIZEOF_REGISTER == 4
13938         /* Create MonoInsts for longs */
13939         for (i = 0; i < cfg->num_varinfo; i++) {
13940                 MonoInst *ins = cfg->varinfo [i];
13941
13942                 if ((ins->opcode != OP_REGVAR) && !(ins->flags & MONO_INST_IS_DEAD)) {
13943                         switch (ins->type) {
13944                         case STACK_R8:
13945                         case STACK_I8: {
13946                                 MonoInst *tree;
13947
13948                                 if (ins->type == STACK_R8 && !COMPILE_SOFT_FLOAT (cfg))
13949                                         break;
13950
13951                                 g_assert (ins->opcode == OP_REGOFFSET);
13952
13953                                 tree = get_vreg_to_inst (cfg, ins->dreg + 1);
13954                                 g_assert (tree);
13955                                 tree->opcode = OP_REGOFFSET;
13956                                 tree->inst_basereg = ins->inst_basereg;
13957                                 tree->inst_offset = ins->inst_offset + MINI_LS_WORD_OFFSET;
13958
13959                                 tree = get_vreg_to_inst (cfg, ins->dreg + 2);
13960                                 g_assert (tree);
13961                                 tree->opcode = OP_REGOFFSET;
13962                                 tree->inst_basereg = ins->inst_basereg;
13963                                 tree->inst_offset = ins->inst_offset + MINI_MS_WORD_OFFSET;
13964                                 break;
13965                         }
13966                         default:
13967                                 break;
13968                         }
13969                 }
13970         }
13971 #endif
13972
13973         if (cfg->compute_gc_maps) {
13974                 /* registers need liveness info even for !non refs */
13975                 for (i = 0; i < cfg->num_varinfo; i++) {
13976                         MonoInst *ins = cfg->varinfo [i];
13977
13978                         if (ins->opcode == OP_REGVAR)
13979                                 ins->flags |= MONO_INST_GC_TRACK;
13980                 }
13981         }
13982
13983         if (cfg->gsharedvt) {
13984                 gsharedvt_vreg_to_idx = mono_mempool_alloc0 (cfg->mempool, sizeof (int) * cfg->next_vreg);
13985
13986                 for (i = 0; i < cfg->num_varinfo; ++i) {
13987                         MonoInst *ins = cfg->varinfo [i];
13988                         int idx;
13989
13990                         if (mini_is_gsharedvt_variable_type (ins->inst_vtype)) {
13991                                 if (i >= cfg->locals_start) {
13992                                         /* Local */
13993                                         idx = get_gsharedvt_info_slot (cfg, ins->inst_vtype, MONO_RGCTX_INFO_LOCAL_OFFSET);
13994                                         gsharedvt_vreg_to_idx [ins->dreg] = idx + 1;
13995                                         ins->opcode = OP_GSHAREDVT_LOCAL;
13996                                         ins->inst_imm = idx;
13997                                 } else {
13998                                         /* Arg */
13999                                         gsharedvt_vreg_to_idx [ins->dreg] = -1;
14000                                         ins->opcode = OP_GSHAREDVT_ARG_REGOFFSET;
14001                                 }
14002                         }
14003                 }
14004         }
14005                 
14006         /* FIXME: widening and truncation */
14007
14008         /*
14009          * As an optimization, when a variable allocated to the stack is first loaded into 
14010          * an lvreg, we will remember the lvreg and use it the next time instead of loading
14011          * the variable again.
14012          */
14013         orig_next_vreg = cfg->next_vreg;
14014         vreg_to_lvreg = mono_mempool_alloc0 (cfg->mempool, sizeof (guint32) * cfg->next_vreg);
14015         lvregs = mono_mempool_alloc (cfg->mempool, sizeof (guint32) * 1024);
14016         lvregs_len = 0;
14017
14018         /* 
14019          * These arrays contain the first and last instructions accessing a given
14020          * variable.
14021          * Since we emit bblocks in the same order we process them here, and we
14022          * don't split live ranges, these will precisely describe the live range of
14023          * the variable, i.e. the instruction range where a valid value can be found
14024          * in the variables location.
14025          * The live range is computed using the liveness info computed by the liveness pass.
14026          * We can't use vmv->range, since that is an abstract live range, and we need
14027          * one which is instruction precise.
14028          * FIXME: Variables used in out-of-line bblocks have a hole in their live range.
14029          */
14030         /* FIXME: Only do this if debugging info is requested */
14031         live_range_start = g_new0 (MonoInst*, cfg->next_vreg);
14032         live_range_end = g_new0 (MonoInst*, cfg->next_vreg);
14033         live_range_start_bb = g_new (MonoBasicBlock*, cfg->next_vreg);
14034         live_range_end_bb = g_new (MonoBasicBlock*, cfg->next_vreg);
14035         
14036         /* Add spill loads/stores */
14037         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
14038                 MonoInst *ins;
14039
14040                 if (cfg->verbose_level > 2)
14041                         printf ("\nSPILL BLOCK %d:\n", bb->block_num);
14042
14043                 /* Clear vreg_to_lvreg array */
14044                 for (i = 0; i < lvregs_len; i++)
14045                         vreg_to_lvreg [lvregs [i]] = 0;
14046                 lvregs_len = 0;
14047
14048                 cfg->cbb = bb;
14049                 MONO_BB_FOR_EACH_INS (bb, ins) {
14050                         const char *spec = INS_INFO (ins->opcode);
14051                         int regtype, srcindex, sreg, tmp_reg, prev_dreg, num_sregs;
14052                         gboolean store, no_lvreg;
14053                         int sregs [MONO_MAX_SRC_REGS];
14054
14055                         if (G_UNLIKELY (cfg->verbose_level > 2))
14056                                 mono_print_ins (ins);
14057
14058                         if (ins->opcode == OP_NOP)
14059                                 continue;
14060
14061                         /* 
14062                          * We handle LDADDR here as well, since it can only be decomposed
14063                          * when variable addresses are known.
14064                          */
14065                         if (ins->opcode == OP_LDADDR) {
14066                                 MonoInst *var = ins->inst_p0;
14067
14068                                 if (var->opcode == OP_VTARG_ADDR) {
14069                                         /* Happens on SPARC/S390 where vtypes are passed by reference */
14070                                         MonoInst *vtaddr = var->inst_left;
14071                                         if (vtaddr->opcode == OP_REGVAR) {
14072                                                 ins->opcode = OP_MOVE;
14073                                                 ins->sreg1 = vtaddr->dreg;
14074                                         }
14075                                         else if (var->inst_left->opcode == OP_REGOFFSET) {
14076                                                 ins->opcode = OP_LOAD_MEMBASE;
14077                                                 ins->inst_basereg = vtaddr->inst_basereg;
14078                                                 ins->inst_offset = vtaddr->inst_offset;
14079                                         } else
14080                                                 NOT_IMPLEMENTED;
14081                                 } else if (cfg->gsharedvt && gsharedvt_vreg_to_idx [var->dreg] < 0) {
14082                                         /* gsharedvt arg passed by ref */
14083                                         g_assert (var->opcode == OP_GSHAREDVT_ARG_REGOFFSET);
14084
14085                                         ins->opcode = OP_LOAD_MEMBASE;
14086                                         ins->inst_basereg = var->inst_basereg;
14087                                         ins->inst_offset = var->inst_offset;
14088                                 } else if (cfg->gsharedvt && gsharedvt_vreg_to_idx [var->dreg]) {
14089                                         MonoInst *load, *load2, *load3;
14090                                         int idx = gsharedvt_vreg_to_idx [var->dreg] - 1;
14091                                         int reg1, reg2, reg3;
14092                                         MonoInst *info_var = cfg->gsharedvt_info_var;
14093                                         MonoInst *locals_var = cfg->gsharedvt_locals_var;
14094
14095                                         /*
14096                                          * gsharedvt local.
14097                                          * Compute the address of the local as gsharedvt_locals_var + gsharedvt_info_var->locals_offsets [idx].
14098                                          */
14099
14100                                         g_assert (var->opcode == OP_GSHAREDVT_LOCAL);
14101
14102                                         g_assert (info_var);
14103                                         g_assert (locals_var);
14104
14105                                         /* Mark the instruction used to compute the locals var as used */
14106                                         cfg->gsharedvt_locals_var_ins = NULL;
14107
14108                                         /* Load the offset */
14109                                         if (info_var->opcode == OP_REGOFFSET) {
14110                                                 reg1 = alloc_ireg (cfg);
14111                                                 NEW_LOAD_MEMBASE (cfg, load, OP_LOAD_MEMBASE, reg1, info_var->inst_basereg, info_var->inst_offset);
14112                                         } else if (info_var->opcode == OP_REGVAR) {
14113                                                 load = NULL;
14114                                                 reg1 = info_var->dreg;
14115                                         } else {
14116                                                 g_assert_not_reached ();
14117                                         }
14118                                         reg2 = alloc_ireg (cfg);
14119                                         NEW_LOAD_MEMBASE (cfg, load2, OP_LOADI4_MEMBASE, reg2, reg1, MONO_STRUCT_OFFSET (MonoGSharedVtMethodRuntimeInfo, entries) + (idx * sizeof (gpointer)));
14120                                         /* Load the locals area address */
14121                                         reg3 = alloc_ireg (cfg);
14122                                         if (locals_var->opcode == OP_REGOFFSET) {
14123                                                 NEW_LOAD_MEMBASE (cfg, load3, OP_LOAD_MEMBASE, reg3, locals_var->inst_basereg, locals_var->inst_offset);
14124                                         } else if (locals_var->opcode == OP_REGVAR) {
14125                                                 NEW_UNALU (cfg, load3, OP_MOVE, reg3, locals_var->dreg);
14126                                         } else {
14127                                                 g_assert_not_reached ();
14128                                         }
14129                                         /* Compute the address */
14130                                         ins->opcode = OP_PADD;
14131                                         ins->sreg1 = reg3;
14132                                         ins->sreg2 = reg2;
14133
14134                                         mono_bblock_insert_before_ins (bb, ins, load3);
14135                                         mono_bblock_insert_before_ins (bb, load3, load2);
14136                                         if (load)
14137                                                 mono_bblock_insert_before_ins (bb, load2, load);
14138                                 } else {
14139                                         g_assert (var->opcode == OP_REGOFFSET);
14140
14141                                         ins->opcode = OP_ADD_IMM;
14142                                         ins->sreg1 = var->inst_basereg;
14143                                         ins->inst_imm = var->inst_offset;
14144                                 }
14145
14146                                 *need_local_opts = TRUE;
14147                                 spec = INS_INFO (ins->opcode);
14148                         }
14149
14150                         if (ins->opcode < MONO_CEE_LAST) {
14151                                 mono_print_ins (ins);
14152                                 g_assert_not_reached ();
14153                         }
14154
14155                         /*
14156                          * Store opcodes have destbasereg in the dreg, but in reality, it is an
14157                          * src register.
14158                          * FIXME:
14159                          */
14160                         if (MONO_IS_STORE_MEMBASE (ins)) {
14161                                 tmp_reg = ins->dreg;
14162                                 ins->dreg = ins->sreg2;
14163                                 ins->sreg2 = tmp_reg;
14164                                 store = TRUE;
14165
14166                                 spec2 [MONO_INST_DEST] = ' ';
14167                                 spec2 [MONO_INST_SRC1] = spec [MONO_INST_SRC1];
14168                                 spec2 [MONO_INST_SRC2] = spec [MONO_INST_DEST];
14169                                 spec2 [MONO_INST_SRC3] = ' ';
14170                                 spec = spec2;
14171                         } else if (MONO_IS_STORE_MEMINDEX (ins))
14172                                 g_assert_not_reached ();
14173                         else
14174                                 store = FALSE;
14175                         no_lvreg = FALSE;
14176
14177                         if (G_UNLIKELY (cfg->verbose_level > 2)) {
14178                                 printf ("\t %.3s %d", spec, ins->dreg);
14179                                 num_sregs = mono_inst_get_src_registers (ins, sregs);
14180                                 for (srcindex = 0; srcindex < num_sregs; ++srcindex)
14181                                         printf (" %d", sregs [srcindex]);
14182                                 printf ("\n");
14183                         }
14184
14185                         /***************/
14186                         /*    DREG     */
14187                         /***************/
14188                         regtype = spec [MONO_INST_DEST];
14189                         g_assert (((ins->dreg == -1) && (regtype == ' ')) || ((ins->dreg != -1) && (regtype != ' ')));
14190                         prev_dreg = -1;
14191
14192                         if ((ins->dreg != -1) && get_vreg_to_inst (cfg, ins->dreg)) {
14193                                 MonoInst *var = get_vreg_to_inst (cfg, ins->dreg);
14194                                 MonoInst *store_ins;
14195                                 int store_opcode;
14196                                 MonoInst *def_ins = ins;
14197                                 int dreg = ins->dreg; /* The original vreg */
14198
14199                                 store_opcode = mono_type_to_store_membase (cfg, var->inst_vtype);
14200
14201                                 if (var->opcode == OP_REGVAR) {
14202                                         ins->dreg = var->dreg;
14203                                 } else if ((ins->dreg == ins->sreg1) && (spec [MONO_INST_DEST] == 'i') && (spec [MONO_INST_SRC1] == 'i') && !vreg_to_lvreg [ins->dreg] && (op_to_op_dest_membase (store_opcode, ins->opcode) != -1)) {
14204                                         /* 
14205                                          * Instead of emitting a load+store, use a _membase opcode.
14206                                          */
14207                                         g_assert (var->opcode == OP_REGOFFSET);
14208                                         if (ins->opcode == OP_MOVE) {
14209                                                 NULLIFY_INS (ins);
14210                                                 def_ins = NULL;
14211                                         } else {
14212                                                 ins->opcode = op_to_op_dest_membase (store_opcode, ins->opcode);
14213                                                 ins->inst_basereg = var->inst_basereg;
14214                                                 ins->inst_offset = var->inst_offset;
14215                                                 ins->dreg = -1;
14216                                         }
14217                                         spec = INS_INFO (ins->opcode);
14218                                 } else {
14219                                         guint32 lvreg;
14220
14221                                         g_assert (var->opcode == OP_REGOFFSET);
14222
14223                                         prev_dreg = ins->dreg;
14224
14225                                         /* Invalidate any previous lvreg for this vreg */
14226                                         vreg_to_lvreg [ins->dreg] = 0;
14227
14228                                         lvreg = 0;
14229
14230                                         if (COMPILE_SOFT_FLOAT (cfg) && store_opcode == OP_STORER8_MEMBASE_REG) {
14231                                                 regtype = 'l';
14232                                                 store_opcode = OP_STOREI8_MEMBASE_REG;
14233                                         }
14234
14235                                         ins->dreg = alloc_dreg (cfg, stacktypes [regtype]);
14236
14237 #if SIZEOF_REGISTER != 8
14238                                         if (regtype == 'l') {
14239                                                 NEW_STORE_MEMBASE (cfg, store_ins, OP_STOREI4_MEMBASE_REG, var->inst_basereg, var->inst_offset + MINI_LS_WORD_OFFSET, ins->dreg + 1);
14240                                                 mono_bblock_insert_after_ins (bb, ins, store_ins);
14241                                                 NEW_STORE_MEMBASE (cfg, store_ins, OP_STOREI4_MEMBASE_REG, var->inst_basereg, var->inst_offset + MINI_MS_WORD_OFFSET, ins->dreg + 2);
14242                                                 mono_bblock_insert_after_ins (bb, ins, store_ins);
14243                                                 def_ins = store_ins;
14244                                         }
14245                                         else
14246 #endif
14247                                         {
14248                                                 g_assert (store_opcode != OP_STOREV_MEMBASE);
14249
14250                                                 /* Try to fuse the store into the instruction itself */
14251                                                 /* FIXME: Add more instructions */
14252                                                 if (!lvreg && ((ins->opcode == OP_ICONST) || ((ins->opcode == OP_I8CONST) && (ins->inst_c0 == 0)))) {
14253                                                         ins->opcode = store_membase_reg_to_store_membase_imm (store_opcode);
14254                                                         ins->inst_imm = ins->inst_c0;
14255                                                         ins->inst_destbasereg = var->inst_basereg;
14256                                                         ins->inst_offset = var->inst_offset;
14257                                                         spec = INS_INFO (ins->opcode);
14258                                                 } else if (!lvreg && ((ins->opcode == OP_MOVE) || (ins->opcode == OP_FMOVE) || (ins->opcode == OP_LMOVE) || (ins->opcode == OP_RMOVE))) {
14259                                                         ins->opcode = store_opcode;
14260                                                         ins->inst_destbasereg = var->inst_basereg;
14261                                                         ins->inst_offset = var->inst_offset;
14262
14263                                                         no_lvreg = TRUE;
14264
14265                                                         tmp_reg = ins->dreg;
14266                                                         ins->dreg = ins->sreg2;
14267                                                         ins->sreg2 = tmp_reg;
14268                                                         store = TRUE;
14269
14270                                                         spec2 [MONO_INST_DEST] = ' ';
14271                                                         spec2 [MONO_INST_SRC1] = spec [MONO_INST_SRC1];
14272                                                         spec2 [MONO_INST_SRC2] = spec [MONO_INST_DEST];
14273                                                         spec2 [MONO_INST_SRC3] = ' ';
14274                                                         spec = spec2;
14275                                                 } else if (!lvreg && (op_to_op_store_membase (store_opcode, ins->opcode) != -1)) {
14276                                                         // FIXME: The backends expect the base reg to be in inst_basereg
14277                                                         ins->opcode = op_to_op_store_membase (store_opcode, ins->opcode);
14278                                                         ins->dreg = -1;
14279                                                         ins->inst_basereg = var->inst_basereg;
14280                                                         ins->inst_offset = var->inst_offset;
14281                                                         spec = INS_INFO (ins->opcode);
14282                                                 } else {
14283                                                         /* printf ("INS: "); mono_print_ins (ins); */
14284                                                         /* Create a store instruction */
14285                                                         NEW_STORE_MEMBASE (cfg, store_ins, store_opcode, var->inst_basereg, var->inst_offset, ins->dreg);
14286
14287                                                         /* Insert it after the instruction */
14288                                                         mono_bblock_insert_after_ins (bb, ins, store_ins);
14289
14290                                                         def_ins = store_ins;
14291
14292                                                         /* 
14293                                                          * We can't assign ins->dreg to var->dreg here, since the
14294                                                          * sregs could use it. So set a flag, and do it after
14295                                                          * the sregs.
14296                                                          */
14297                                                         if ((!cfg->backend->use_fpstack || ((store_opcode != OP_STORER8_MEMBASE_REG) && (store_opcode != OP_STORER4_MEMBASE_REG))) && !((var)->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)))
14298                                                                 dest_has_lvreg = TRUE;
14299                                                 }
14300                                         }
14301                                 }
14302
14303                                 if (def_ins && !live_range_start [dreg]) {
14304                                         live_range_start [dreg] = def_ins;
14305                                         live_range_start_bb [dreg] = bb;
14306                                 }
14307
14308                                 if (cfg->compute_gc_maps && def_ins && (var->flags & MONO_INST_GC_TRACK)) {
14309                                         MonoInst *tmp;
14310
14311                                         MONO_INST_NEW (cfg, tmp, OP_GC_LIVENESS_DEF);
14312                                         tmp->inst_c1 = dreg;
14313                                         mono_bblock_insert_after_ins (bb, def_ins, tmp);
14314                                 }
14315                         }
14316
14317                         /************/
14318                         /*  SREGS   */
14319                         /************/
14320                         num_sregs = mono_inst_get_src_registers (ins, sregs);
14321                         for (srcindex = 0; srcindex < 3; ++srcindex) {
14322                                 regtype = spec [MONO_INST_SRC1 + srcindex];
14323                                 sreg = sregs [srcindex];
14324
14325                                 g_assert (((sreg == -1) && (regtype == ' ')) || ((sreg != -1) && (regtype != ' ')));
14326                                 if ((sreg != -1) && get_vreg_to_inst (cfg, sreg)) {
14327                                         MonoInst *var = get_vreg_to_inst (cfg, sreg);
14328                                         MonoInst *use_ins = ins;
14329                                         MonoInst *load_ins;
14330                                         guint32 load_opcode;
14331
14332                                         if (var->opcode == OP_REGVAR) {
14333                                                 sregs [srcindex] = var->dreg;
14334                                                 //mono_inst_set_src_registers (ins, sregs);
14335                                                 live_range_end [sreg] = use_ins;
14336                                                 live_range_end_bb [sreg] = bb;
14337
14338                                                 if (cfg->compute_gc_maps && var->dreg < orig_next_vreg && (var->flags & MONO_INST_GC_TRACK)) {
14339                                                         MonoInst *tmp;
14340
14341                                                         MONO_INST_NEW (cfg, tmp, OP_GC_LIVENESS_USE);
14342                                                         /* var->dreg is a hreg */
14343                                                         tmp->inst_c1 = sreg;
14344                                                         mono_bblock_insert_after_ins (bb, ins, tmp);
14345                                                 }
14346
14347                                                 continue;
14348                                         }
14349
14350                                         g_assert (var->opcode == OP_REGOFFSET);
14351                                                 
14352                                         load_opcode = mono_type_to_load_membase (cfg, var->inst_vtype);
14353
14354                                         g_assert (load_opcode != OP_LOADV_MEMBASE);
14355
14356                                         if (vreg_to_lvreg [sreg]) {
14357                                                 g_assert (vreg_to_lvreg [sreg] != -1);
14358
14359                                                 /* The variable is already loaded to an lvreg */
14360                                                 if (G_UNLIKELY (cfg->verbose_level > 2))
14361                                                         printf ("\t\tUse lvreg R%d for R%d.\n", vreg_to_lvreg [sreg], sreg);
14362                                                 sregs [srcindex] = vreg_to_lvreg [sreg];
14363                                                 //mono_inst_set_src_registers (ins, sregs);
14364                                                 continue;
14365                                         }
14366
14367                                         /* Try to fuse the load into the instruction */
14368                                         if ((srcindex == 0) && (op_to_op_src1_membase (cfg, load_opcode, ins->opcode) != -1)) {
14369                                                 ins->opcode = op_to_op_src1_membase (cfg, load_opcode, ins->opcode);
14370                                                 sregs [0] = var->inst_basereg;
14371                                                 //mono_inst_set_src_registers (ins, sregs);
14372                                                 ins->inst_offset = var->inst_offset;
14373                                         } else if ((srcindex == 1) && (op_to_op_src2_membase (cfg, load_opcode, ins->opcode) != -1)) {
14374                                                 ins->opcode = op_to_op_src2_membase (cfg, load_opcode, ins->opcode);
14375                                                 sregs [1] = var->inst_basereg;
14376                                                 //mono_inst_set_src_registers (ins, sregs);
14377                                                 ins->inst_offset = var->inst_offset;
14378                                         } else {
14379                                                 if (MONO_IS_REAL_MOVE (ins)) {
14380                                                         ins->opcode = OP_NOP;
14381                                                         sreg = ins->dreg;
14382                                                 } else {
14383                                                         //printf ("%d ", srcindex); mono_print_ins (ins);
14384
14385                                                         sreg = alloc_dreg (cfg, stacktypes [regtype]);
14386
14387                                                         if ((!cfg->backend->use_fpstack || ((load_opcode != OP_LOADR8_MEMBASE) && (load_opcode != OP_LOADR4_MEMBASE))) && !((var)->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT)) && !no_lvreg) {
14388                                                                 if (var->dreg == prev_dreg) {
14389                                                                         /*
14390                                                                          * sreg refers to the value loaded by the load
14391                                                                          * emitted below, but we need to use ins->dreg
14392                                                                          * since it refers to the store emitted earlier.
14393                                                                          */
14394                                                                         sreg = ins->dreg;
14395                                                                 }
14396                                                                 g_assert (sreg != -1);
14397                                                                 vreg_to_lvreg [var->dreg] = sreg;
14398                                                                 g_assert (lvregs_len < 1024);
14399                                                                 lvregs [lvregs_len ++] = var->dreg;
14400                                                         }
14401                                                 }
14402
14403                                                 sregs [srcindex] = sreg;
14404                                                 //mono_inst_set_src_registers (ins, sregs);
14405
14406 #if SIZEOF_REGISTER != 8
14407                                                 if (regtype == 'l') {
14408                                                         NEW_LOAD_MEMBASE (cfg, load_ins, OP_LOADI4_MEMBASE, sreg + 2, var->inst_basereg, var->inst_offset + MINI_MS_WORD_OFFSET);
14409                                                         mono_bblock_insert_before_ins (bb, ins, load_ins);
14410                                                         NEW_LOAD_MEMBASE (cfg, load_ins, OP_LOADI4_MEMBASE, sreg + 1, var->inst_basereg, var->inst_offset + MINI_LS_WORD_OFFSET);
14411                                                         mono_bblock_insert_before_ins (bb, ins, load_ins);
14412                                                         use_ins = load_ins;
14413                                                 }
14414                                                 else
14415 #endif
14416                                                 {
14417 #if SIZEOF_REGISTER == 4
14418                                                         g_assert (load_opcode != OP_LOADI8_MEMBASE);
14419 #endif
14420                                                         NEW_LOAD_MEMBASE (cfg, load_ins, load_opcode, sreg, var->inst_basereg, var->inst_offset);
14421                                                         mono_bblock_insert_before_ins (bb, ins, load_ins);
14422                                                         use_ins = load_ins;
14423                                                 }
14424                                         }
14425
14426                                         if (var->dreg < orig_next_vreg) {
14427                                                 live_range_end [var->dreg] = use_ins;
14428                                                 live_range_end_bb [var->dreg] = bb;
14429                                         }
14430
14431                                         if (cfg->compute_gc_maps && var->dreg < orig_next_vreg && (var->flags & MONO_INST_GC_TRACK)) {
14432                                                 MonoInst *tmp;
14433
14434                                                 MONO_INST_NEW (cfg, tmp, OP_GC_LIVENESS_USE);
14435                                                 tmp->inst_c1 = var->dreg;
14436                                                 mono_bblock_insert_after_ins (bb, ins, tmp);
14437                                         }
14438                                 }
14439                         }
14440                         mono_inst_set_src_registers (ins, sregs);
14441
14442                         if (dest_has_lvreg) {
14443                                 g_assert (ins->dreg != -1);
14444                                 vreg_to_lvreg [prev_dreg] = ins->dreg;
14445                                 g_assert (lvregs_len < 1024);
14446                                 lvregs [lvregs_len ++] = prev_dreg;
14447                                 dest_has_lvreg = FALSE;
14448                         }
14449
14450                         if (store) {
14451                                 tmp_reg = ins->dreg;
14452                                 ins->dreg = ins->sreg2;
14453                                 ins->sreg2 = tmp_reg;
14454                         }
14455
14456                         if (MONO_IS_CALL (ins)) {
14457                                 /* Clear vreg_to_lvreg array */
14458                                 for (i = 0; i < lvregs_len; i++)
14459                                         vreg_to_lvreg [lvregs [i]] = 0;
14460                                 lvregs_len = 0;
14461                         } else if (ins->opcode == OP_NOP) {
14462                                 ins->dreg = -1;
14463                                 MONO_INST_NULLIFY_SREGS (ins);
14464                         }
14465
14466                         if (cfg->verbose_level > 2)
14467                                 mono_print_ins_index (1, ins);
14468                 }
14469
14470                 /* Extend the live range based on the liveness info */
14471                 if (cfg->compute_precise_live_ranges && bb->live_out_set && bb->code) {
14472                         for (i = 0; i < cfg->num_varinfo; i ++) {
14473                                 MonoMethodVar *vi = MONO_VARINFO (cfg, i);
14474
14475                                 if (vreg_is_volatile (cfg, vi->vreg))
14476                                         /* The liveness info is incomplete */
14477                                         continue;
14478
14479                                 if (mono_bitset_test_fast (bb->live_in_set, i) && !live_range_start [vi->vreg]) {
14480                                         /* Live from at least the first ins of this bb */
14481                                         live_range_start [vi->vreg] = bb->code;
14482                                         live_range_start_bb [vi->vreg] = bb;
14483                                 }
14484
14485                                 if (mono_bitset_test_fast (bb->live_out_set, i)) {
14486                                         /* Live at least until the last ins of this bb */
14487                                         live_range_end [vi->vreg] = bb->last_ins;
14488                                         live_range_end_bb [vi->vreg] = bb;
14489                                 }
14490                         }
14491                 }
14492         }
14493         
14494         /*
14495          * Emit LIVERANGE_START/LIVERANGE_END opcodes, the backend will implement them
14496          * by storing the current native offset into MonoMethodVar->live_range_start/end.
14497          */
14498         if (cfg->backend->have_liverange_ops && cfg->compute_precise_live_ranges && cfg->comp_done & MONO_COMP_LIVENESS) {
14499                 for (i = 0; i < cfg->num_varinfo; ++i) {
14500                         int vreg = MONO_VARINFO (cfg, i)->vreg;
14501                         MonoInst *ins;
14502
14503                         if (live_range_start [vreg]) {
14504                                 MONO_INST_NEW (cfg, ins, OP_LIVERANGE_START);
14505                                 ins->inst_c0 = i;
14506                                 ins->inst_c1 = vreg;
14507                                 mono_bblock_insert_after_ins (live_range_start_bb [vreg], live_range_start [vreg], ins);
14508                         }
14509                         if (live_range_end [vreg]) {
14510                                 MONO_INST_NEW (cfg, ins, OP_LIVERANGE_END);
14511                                 ins->inst_c0 = i;
14512                                 ins->inst_c1 = vreg;
14513                                 if (live_range_end [vreg] == live_range_end_bb [vreg]->last_ins)
14514                                         mono_add_ins_to_end (live_range_end_bb [vreg], ins);
14515                                 else
14516                                         mono_bblock_insert_after_ins (live_range_end_bb [vreg], live_range_end [vreg], ins);
14517                         }
14518                 }
14519         }
14520
14521         if (cfg->gsharedvt_locals_var_ins) {
14522                 /* Nullify if unused */
14523                 cfg->gsharedvt_locals_var_ins->opcode = OP_PCONST;
14524                 cfg->gsharedvt_locals_var_ins->inst_imm = 0;
14525         }
14526
14527         g_free (live_range_start);
14528         g_free (live_range_end);
14529         g_free (live_range_start_bb);
14530         g_free (live_range_end_bb);
14531 }
14532
14533 /**
14534  * FIXME:
14535  * - use 'iadd' instead of 'int_add'
14536  * - handling ovf opcodes: decompose in method_to_ir.
14537  * - unify iregs/fregs
14538  *   -> partly done, the missing parts are:
14539  *   - a more complete unification would involve unifying the hregs as well, so
14540  *     code wouldn't need if (fp) all over the place. but that would mean the hregs
14541  *     would no longer map to the machine hregs, so the code generators would need to
14542  *     be modified. Also, on ia64 for example, niregs + nfregs > 256 -> bitmasks
14543  *     wouldn't work any more. Duplicating the code in mono_local_regalloc () into
14544  *     fp/non-fp branches speeds it up by about 15%.
14545  * - use sext/zext opcodes instead of shifts
14546  * - add OP_ICALL
14547  * - get rid of TEMPLOADs if possible and use vregs instead
14548  * - clean up usage of OP_P/OP_ opcodes
14549  * - cleanup usage of DUMMY_USE
14550  * - cleanup the setting of ins->type for MonoInst's which are pushed on the 
14551  *   stack
14552  * - set the stack type and allocate a dreg in the EMIT_NEW macros
14553  * - get rid of all the <foo>2 stuff when the new JIT is ready.
14554  * - make sure handle_stack_args () is called before the branch is emitted
14555  * - when the new IR is done, get rid of all unused stuff
14556  * - COMPARE/BEQ as separate instructions or unify them ?
14557  *   - keeping them separate allows specialized compare instructions like
14558  *     compare_imm, compare_membase
14559  *   - most back ends unify fp compare+branch, fp compare+ceq
14560  * - integrate mono_save_args into inline_method
14561  * - get rid of the empty bblocks created by MONO_EMIT_NEW_BRACH_BLOCK2
14562  * - handle long shift opts on 32 bit platforms somehow: they require 
14563  *   3 sregs (2 for arg1 and 1 for arg2)
14564  * - make byref a 'normal' type.
14565  * - use vregs for bb->out_stacks if possible, handle_global_vreg will make them a
14566  *   variable if needed.
14567  * - do not start a new IL level bblock when cfg->cbb is changed by a function call
14568  *   like inline_method.
14569  * - remove inlining restrictions
14570  * - fix LNEG and enable cfold of INEG
14571  * - generalize x86 optimizations like ldelema as a peephole optimization
14572  * - add store_mem_imm for amd64
14573  * - optimize the loading of the interruption flag in the managed->native wrappers
14574  * - avoid special handling of OP_NOP in passes
14575  * - move code inserting instructions into one function/macro.
14576  * - try a coalescing phase after liveness analysis
14577  * - add float -> vreg conversion + local optimizations on !x86
14578  * - figure out how to handle decomposed branches during optimizations, ie.
14579  *   compare+branch, op_jump_table+op_br etc.
14580  * - promote RuntimeXHandles to vregs
14581  * - vtype cleanups:
14582  *   - add a NEW_VARLOADA_VREG macro
14583  * - the vtype optimizations are blocked by the LDADDR opcodes generated for 
14584  *   accessing vtype fields.
14585  * - get rid of I8CONST on 64 bit platforms
14586  * - dealing with the increase in code size due to branches created during opcode
14587  *   decomposition:
14588  *   - use extended basic blocks
14589  *     - all parts of the JIT
14590  *     - handle_global_vregs () && local regalloc
14591  *   - avoid introducing global vregs during decomposition, like 'vtable' in isinst
14592  * - sources of increase in code size:
14593  *   - vtypes
14594  *   - long compares
14595  *   - isinst and castclass
14596  *   - lvregs not allocated to global registers even if used multiple times
14597  * - call cctors outside the JIT, to make -v output more readable and JIT timings more
14598  *   meaningful.
14599  * - check for fp stack leakage in other opcodes too. (-> 'exceptions' optimization)
14600  * - add all micro optimizations from the old JIT
14601  * - put tree optimizations into the deadce pass
14602  * - decompose op_start_handler/op_endfilter/op_endfinally earlier using an arch
14603  *   specific function.
14604  * - unify the float comparison opcodes with the other comparison opcodes, i.e.
14605  *   fcompare + branchCC.
14606  * - create a helper function for allocating a stack slot, taking into account 
14607  *   MONO_CFG_HAS_SPILLUP.
14608  * - merge r68207.
14609  * - merge the ia64 switch changes.
14610  * - optimize mono_regstate2_alloc_int/float.
14611  * - fix the pessimistic handling of variables accessed in exception handler blocks.
14612  * - need to write a tree optimization pass, but the creation of trees is difficult, i.e.
14613  *   parts of the tree could be separated by other instructions, killing the tree
14614  *   arguments, or stores killing loads etc. Also, should we fold loads into other
14615  *   instructions if the result of the load is used multiple times ?
14616  * - make the REM_IMM optimization in mini-x86.c arch-independent.
14617  * - LAST MERGE: 108395.
14618  * - when returning vtypes in registers, generate IR and append it to the end of the
14619  *   last bb instead of doing it in the epilog.
14620  * - change the store opcodes so they use sreg1 instead of dreg to store the base register.
14621  */
14622
14623 /*
14624
14625 NOTES
14626 -----
14627
14628 - When to decompose opcodes:
14629   - earlier: this makes some optimizations hard to implement, since the low level IR
14630   no longer contains the neccessary information. But it is easier to do.
14631   - later: harder to implement, enables more optimizations.
14632 - Branches inside bblocks:
14633   - created when decomposing complex opcodes. 
14634     - branches to another bblock: harmless, but not tracked by the branch 
14635       optimizations, so need to branch to a label at the start of the bblock.
14636     - branches to inside the same bblock: very problematic, trips up the local
14637       reg allocator. Can be fixed by spitting the current bblock, but that is a
14638       complex operation, since some local vregs can become global vregs etc.
14639 - Local/global vregs:
14640   - local vregs: temporary vregs used inside one bblock. Assigned to hregs by the
14641     local register allocator.
14642   - global vregs: used in more than one bblock. Have an associated MonoMethodVar
14643     structure, created by mono_create_var (). Assigned to hregs or the stack by
14644     the global register allocator.
14645 - When to do optimizations like alu->alu_imm:
14646   - earlier -> saves work later on since the IR will be smaller/simpler
14647   - later -> can work on more instructions
14648 - Handling of valuetypes:
14649   - When a vtype is pushed on the stack, a new temporary is created, an 
14650     instruction computing its address (LDADDR) is emitted and pushed on
14651     the stack. Need to optimize cases when the vtype is used immediately as in
14652     argument passing, stloc etc.
14653 - Instead of the to_end stuff in the old JIT, simply call the function handling
14654   the values on the stack before emitting the last instruction of the bb.
14655 */
14656
14657 #endif /* DISABLE_JIT */