Merge pull request #2152 from joelmartinez/mdoc-preserver
[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_buf [16], *icall_args [16];
9589                                 MonoInst **args;
9590                                 MonoBasicBlock *rgctx_bb, *end_bb;
9591                                 MonoInst *call1, *call2, *call_target;
9592                                 MonoMethodSignature *rgctx_sig;
9593                                 int rgctx_reg, tmp_reg;
9594
9595                                 MONO_EMIT_NULL_CHECK (cfg, sp [0]->dreg);
9596
9597                                 NEW_BBLOCK (cfg, rgctx_bb);
9598                                 NEW_BBLOCK (cfg, end_bb);
9599
9600                                 // FIXME: Optimize this
9601
9602                                 guint32 imt_slot = mono_method_get_imt_slot (cmethod);
9603
9604                                 icall_args [0] = sp [0];
9605                                 EMIT_NEW_ICONST (cfg, icall_args [1], imt_slot);
9606                                 if (imt_arg) {
9607                                         icall_args [2] = imt_arg;
9608                                 } else {
9609                                         EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_METHODCONST, cmethod);
9610                                         icall_args [2] = ins;
9611                                 }
9612
9613                                 rgctx_reg = alloc_preg (cfg);
9614                                 MONO_EMIT_NEW_PCONST (cfg, rgctx_reg, NULL);
9615                                 EMIT_NEW_VARLOADA_VREG (cfg, icall_args [3], rgctx_reg, &mono_defaults.int_class->byval_arg);
9616                                 //EMIT_NEW_PCONST (cfg, icall_args [3], NULL);
9617
9618                                 call_target = mono_emit_jit_icall (cfg, mono_resolve_iface_call, icall_args);
9619
9620                                 // FIXME: Only do this if needed (generic calls)
9621
9622                                 // Check whenever to pass an rgctx
9623                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, rgctx_reg, 0);
9624                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBNE_UN, rgctx_bb);
9625                                 /* Non rgctx case */
9626                                 call1 = mono_emit_calli (cfg, fsig, sp, call_target, NULL, vtable_arg);
9627                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
9628                                 /* Rgctx case */
9629                                 MONO_START_BB (cfg, rgctx_bb);
9630                                 /* Make a call with an rgctx */
9631                                 if (fsig->param_count + 2 < 16)
9632                                         args = args_buf;
9633                                 else
9634                                         args = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst*) * (fsig->param_count + 2));
9635                                 args [0] = sp [0];
9636                                 for (i = 0; i < fsig->param_count; ++i)
9637                                         args [i + 1] = sp [i + 1];
9638                                 tmp_reg = alloc_preg (cfg);
9639                                 EMIT_NEW_UNALU (cfg, args [fsig->param_count + 1], OP_MOVE, tmp_reg, rgctx_reg);
9640                                 rgctx_sig = sig_to_rgctx_sig (fsig);
9641                                 call2 = mono_emit_calli (cfg, rgctx_sig, args, call_target, NULL, NULL);
9642                                 call2->dreg = call1->dreg;
9643                                 MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb);
9644                                 /* End */
9645                                 MONO_START_BB (cfg, end_bb);
9646                                 ins = call1;
9647                                 goto call_end;
9648                         }
9649
9650                         /* Common call */
9651                         INLINE_FAILURE ("call");
9652                         ins = mono_emit_method_call_full (cfg, cmethod, fsig, tail_call, sp, virtual ? sp [0] : NULL,
9653                                                                                           imt_arg, vtable_arg);
9654
9655                         if (tail_call && !cfg->llvm_only) {
9656                                 link_bblock (cfg, cfg->cbb, end_bblock);
9657                                 start_new_bblock = 1;
9658
9659                                 // FIXME: Eliminate unreachable epilogs
9660
9661                                 /*
9662                                  * OP_TAILCALL has no return value, so skip the CEE_RET if it is
9663                                  * only reachable from this call.
9664                                  */
9665                                 GET_BBLOCK (cfg, tblock, ip + 5);
9666                                 if (tblock == cfg->cbb || tblock->in_count == 0)
9667                                         skip_ret = TRUE;
9668                                 push_res = FALSE;
9669                         }
9670
9671                         call_end:
9672
9673                         /* End of call, INS should contain the result of the call, if any */
9674
9675                         if (push_res && !MONO_TYPE_IS_VOID (fsig->ret)) {
9676                                 g_assert (ins);
9677                                 if (emit_widen)
9678                                         *sp++ = mono_emit_widen_call_res (cfg, ins, fsig);
9679                                 else
9680                                         *sp++ = ins;
9681                         }
9682
9683                         if (keep_this_alive) {
9684                                 MonoInst *dummy_use;
9685
9686                                 /* See mono_emit_method_call_full () */
9687                                 EMIT_NEW_DUMMY_USE (cfg, dummy_use, keep_this_alive);
9688                         }
9689
9690                         CHECK_CFG_EXCEPTION;
9691
9692                         ip += 5;
9693                         if (skip_ret) {
9694                                 g_assert (*ip == CEE_RET);
9695                                 ip += 1;
9696                         }
9697                         ins_flag = 0;
9698                         constrained_class = NULL;
9699                         if (need_seq_point)
9700                                 emit_seq_point (cfg, method, ip, FALSE, TRUE);
9701                         break;
9702                 }
9703                 case CEE_RET:
9704                         if (cfg->method != method) {
9705                                 /* return from inlined method */
9706                                 /* 
9707                                  * If in_count == 0, that means the ret is unreachable due to
9708                                  * being preceeded by a throw. In that case, inline_method () will
9709                                  * handle setting the return value 
9710                                  * (test case: test_0_inline_throw ()).
9711                                  */
9712                                 if (return_var && cfg->cbb->in_count) {
9713                                         MonoType *ret_type = mono_method_signature (method)->ret;
9714
9715                                         MonoInst *store;
9716                                         CHECK_STACK (1);
9717                                         --sp;
9718
9719                                         if ((method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD || method->wrapper_type == MONO_WRAPPER_NONE) && target_type_is_incompatible (cfg, ret_type, *sp))
9720                                                 UNVERIFIED;
9721
9722                                         //g_assert (returnvar != -1);
9723                                         EMIT_NEW_TEMPSTORE (cfg, store, return_var->inst_c0, *sp);
9724                                         cfg->ret_var_set = TRUE;
9725                                 } 
9726                         } else {
9727                                 emit_instrumentation_call (cfg, mono_profiler_method_leave);
9728
9729                                 if (cfg->lmf_var && cfg->cbb->in_count && !cfg->llvm_only)
9730                                         emit_pop_lmf (cfg);
9731
9732                                 if (cfg->ret) {
9733                                         MonoType *ret_type = mini_get_underlying_type (mono_method_signature (method)->ret);
9734
9735                                         if (seq_points && !sym_seq_points) {
9736                                                 /* 
9737                                                  * Place a seq point here too even through the IL stack is not
9738                                                  * empty, so a step over on
9739                                                  * call <FOO>
9740                                                  * ret
9741                                                  * will work correctly.
9742                                                  */
9743                                                 NEW_SEQ_POINT (cfg, ins, ip - header->code, TRUE);
9744                                                 MONO_ADD_INS (cfg->cbb, ins);
9745                                         }
9746
9747                                         g_assert (!return_var);
9748                                         CHECK_STACK (1);
9749                                         --sp;
9750
9751                                         if ((method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD || method->wrapper_type == MONO_WRAPPER_NONE) && target_type_is_incompatible (cfg, ret_type, *sp))
9752                                                 UNVERIFIED;
9753
9754                                         emit_setret (cfg, *sp);
9755                                 }
9756                         }
9757                         if (sp != stack_start)
9758                                 UNVERIFIED;
9759                         MONO_INST_NEW (cfg, ins, OP_BR);
9760                         ip++;
9761                         ins->inst_target_bb = end_bblock;
9762                         MONO_ADD_INS (cfg->cbb, ins);
9763                         link_bblock (cfg, cfg->cbb, end_bblock);
9764                         start_new_bblock = 1;
9765                         break;
9766                 case CEE_BR_S:
9767                         CHECK_OPSIZE (2);
9768                         MONO_INST_NEW (cfg, ins, OP_BR);
9769                         ip++;
9770                         target = ip + 1 + (signed char)(*ip);
9771                         ++ip;
9772                         GET_BBLOCK (cfg, tblock, target);
9773                         link_bblock (cfg, cfg->cbb, tblock);
9774                         ins->inst_target_bb = tblock;
9775                         if (sp != stack_start) {
9776                                 handle_stack_args (cfg, stack_start, sp - stack_start);
9777                                 sp = stack_start;
9778                                 CHECK_UNVERIFIABLE (cfg);
9779                         }
9780                         MONO_ADD_INS (cfg->cbb, ins);
9781                         start_new_bblock = 1;
9782                         inline_costs += BRANCH_COST;
9783                         break;
9784                 case CEE_BEQ_S:
9785                 case CEE_BGE_S:
9786                 case CEE_BGT_S:
9787                 case CEE_BLE_S:
9788                 case CEE_BLT_S:
9789                 case CEE_BNE_UN_S:
9790                 case CEE_BGE_UN_S:
9791                 case CEE_BGT_UN_S:
9792                 case CEE_BLE_UN_S:
9793                 case CEE_BLT_UN_S:
9794                         CHECK_OPSIZE (2);
9795                         CHECK_STACK (2);
9796                         MONO_INST_NEW (cfg, ins, *ip + BIG_BRANCH_OFFSET);
9797                         ip++;
9798                         target = ip + 1 + *(signed char*)ip;
9799                         ip++;
9800
9801                         ADD_BINCOND (NULL);
9802
9803                         sp = stack_start;
9804                         inline_costs += BRANCH_COST;
9805                         break;
9806                 case CEE_BR:
9807                         CHECK_OPSIZE (5);
9808                         MONO_INST_NEW (cfg, ins, OP_BR);
9809                         ip++;
9810
9811                         target = ip + 4 + (gint32)read32(ip);
9812                         ip += 4;
9813                         GET_BBLOCK (cfg, tblock, target);
9814                         link_bblock (cfg, cfg->cbb, tblock);
9815                         ins->inst_target_bb = tblock;
9816                         if (sp != stack_start) {
9817                                 handle_stack_args (cfg, stack_start, sp - stack_start);
9818                                 sp = stack_start;
9819                                 CHECK_UNVERIFIABLE (cfg);
9820                         }
9821
9822                         MONO_ADD_INS (cfg->cbb, ins);
9823
9824                         start_new_bblock = 1;
9825                         inline_costs += BRANCH_COST;
9826                         break;
9827                 case CEE_BRFALSE_S:
9828                 case CEE_BRTRUE_S:
9829                 case CEE_BRFALSE:
9830                 case CEE_BRTRUE: {
9831                         MonoInst *cmp;
9832                         gboolean is_short = ((*ip) == CEE_BRFALSE_S) || ((*ip) == CEE_BRTRUE_S);
9833                         gboolean is_true = ((*ip) == CEE_BRTRUE_S) || ((*ip) == CEE_BRTRUE);
9834                         guint32 opsize = is_short ? 1 : 4;
9835
9836                         CHECK_OPSIZE (opsize);
9837                         CHECK_STACK (1);
9838                         if (sp [-1]->type == STACK_VTYPE || sp [-1]->type == STACK_R8)
9839                                 UNVERIFIED;
9840                         ip ++;
9841                         target = ip + opsize + (is_short ? *(signed char*)ip : (gint32)read32(ip));
9842                         ip += opsize;
9843
9844                         sp--;
9845
9846                         GET_BBLOCK (cfg, tblock, target);
9847                         link_bblock (cfg, cfg->cbb, tblock);
9848                         GET_BBLOCK (cfg, tblock, ip);
9849                         link_bblock (cfg, cfg->cbb, tblock);
9850
9851                         if (sp != stack_start) {
9852                                 handle_stack_args (cfg, stack_start, sp - stack_start);
9853                                 CHECK_UNVERIFIABLE (cfg);
9854                         }
9855
9856                         MONO_INST_NEW(cfg, cmp, OP_ICOMPARE_IMM);
9857                         cmp->sreg1 = sp [0]->dreg;
9858                         type_from_op (cfg, cmp, sp [0], NULL);
9859                         CHECK_TYPE (cmp);
9860
9861 #if SIZEOF_REGISTER == 4
9862                         if (cmp->opcode == OP_LCOMPARE_IMM) {
9863                                 /* Convert it to OP_LCOMPARE */
9864                                 MONO_INST_NEW (cfg, ins, OP_I8CONST);
9865                                 ins->type = STACK_I8;
9866                                 ins->dreg = alloc_dreg (cfg, STACK_I8);
9867                                 ins->inst_l = 0;
9868                                 MONO_ADD_INS (cfg->cbb, ins);
9869                                 cmp->opcode = OP_LCOMPARE;
9870                                 cmp->sreg2 = ins->dreg;
9871                         }
9872 #endif
9873                         MONO_ADD_INS (cfg->cbb, cmp);
9874
9875                         MONO_INST_NEW (cfg, ins, is_true ? CEE_BNE_UN : CEE_BEQ);
9876                         type_from_op (cfg, ins, sp [0], NULL);
9877                         MONO_ADD_INS (cfg->cbb, ins);
9878                         ins->inst_many_bb = mono_mempool_alloc (cfg->mempool, sizeof(gpointer)*2);
9879                         GET_BBLOCK (cfg, tblock, target);
9880                         ins->inst_true_bb = tblock;
9881                         GET_BBLOCK (cfg, tblock, ip);
9882                         ins->inst_false_bb = tblock;
9883                         start_new_bblock = 2;
9884
9885                         sp = stack_start;
9886                         inline_costs += BRANCH_COST;
9887                         break;
9888                 }
9889                 case CEE_BEQ:
9890                 case CEE_BGE:
9891                 case CEE_BGT:
9892                 case CEE_BLE:
9893                 case CEE_BLT:
9894                 case CEE_BNE_UN:
9895                 case CEE_BGE_UN:
9896                 case CEE_BGT_UN:
9897                 case CEE_BLE_UN:
9898                 case CEE_BLT_UN:
9899                         CHECK_OPSIZE (5);
9900                         CHECK_STACK (2);
9901                         MONO_INST_NEW (cfg, ins, *ip);
9902                         ip++;
9903                         target = ip + 4 + (gint32)read32(ip);
9904                         ip += 4;
9905
9906                         ADD_BINCOND (NULL);
9907
9908                         sp = stack_start;
9909                         inline_costs += BRANCH_COST;
9910                         break;
9911                 case CEE_SWITCH: {
9912                         MonoInst *src1;
9913                         MonoBasicBlock **targets;
9914                         MonoBasicBlock *default_bblock;
9915                         MonoJumpInfoBBTable *table;
9916                         int offset_reg = alloc_preg (cfg);
9917                         int target_reg = alloc_preg (cfg);
9918                         int table_reg = alloc_preg (cfg);
9919                         int sum_reg = alloc_preg (cfg);
9920                         gboolean use_op_switch;
9921
9922                         CHECK_OPSIZE (5);
9923                         CHECK_STACK (1);
9924                         n = read32 (ip + 1);
9925                         --sp;
9926                         src1 = sp [0];
9927                         if ((src1->type != STACK_I4) && (src1->type != STACK_PTR)) 
9928                                 UNVERIFIED;
9929
9930                         ip += 5;
9931                         CHECK_OPSIZE (n * sizeof (guint32));
9932                         target = ip + n * sizeof (guint32);
9933
9934                         GET_BBLOCK (cfg, default_bblock, target);
9935                         default_bblock->flags |= BB_INDIRECT_JUMP_TARGET;
9936
9937                         targets = mono_mempool_alloc (cfg->mempool, sizeof (MonoBasicBlock*) * n);
9938                         for (i = 0; i < n; ++i) {
9939                                 GET_BBLOCK (cfg, tblock, target + (gint32)read32(ip));
9940                                 targets [i] = tblock;
9941                                 targets [i]->flags |= BB_INDIRECT_JUMP_TARGET;
9942                                 ip += 4;
9943                         }
9944
9945                         if (sp != stack_start) {
9946                                 /* 
9947                                  * Link the current bb with the targets as well, so handle_stack_args
9948                                  * will set their in_stack correctly.
9949                                  */
9950                                 link_bblock (cfg, cfg->cbb, default_bblock);
9951                                 for (i = 0; i < n; ++i)
9952                                         link_bblock (cfg, cfg->cbb, targets [i]);
9953
9954                                 handle_stack_args (cfg, stack_start, sp - stack_start);
9955                                 sp = stack_start;
9956                                 CHECK_UNVERIFIABLE (cfg);
9957
9958                                 /* Undo the links */
9959                                 mono_unlink_bblock (cfg, cfg->cbb, default_bblock);
9960                                 for (i = 0; i < n; ++i)
9961                                         mono_unlink_bblock (cfg, cfg->cbb, targets [i]);
9962                         }
9963
9964                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ICOMPARE_IMM, -1, src1->dreg, n);
9965                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBGE_UN, default_bblock);
9966
9967                         for (i = 0; i < n; ++i)
9968                                 link_bblock (cfg, cfg->cbb, targets [i]);
9969
9970                         table = mono_mempool_alloc (cfg->mempool, sizeof (MonoJumpInfoBBTable));
9971                         table->table = targets;
9972                         table->table_size = n;
9973
9974                         use_op_switch = FALSE;
9975 #ifdef TARGET_ARM
9976                         /* ARM implements SWITCH statements differently */
9977                         /* FIXME: Make it use the generic implementation */
9978                         if (!cfg->compile_aot)
9979                                 use_op_switch = TRUE;
9980 #endif
9981
9982                         if (COMPILE_LLVM (cfg))
9983                                 use_op_switch = TRUE;
9984
9985                         cfg->cbb->has_jump_table = 1;
9986
9987                         if (use_op_switch) {
9988                                 MONO_INST_NEW (cfg, ins, OP_SWITCH);
9989                                 ins->sreg1 = src1->dreg;
9990                                 ins->inst_p0 = table;
9991                                 ins->inst_many_bb = targets;
9992                                 ins->klass = GUINT_TO_POINTER (n);
9993                                 MONO_ADD_INS (cfg->cbb, ins);
9994                         } else {
9995                                 if (sizeof (gpointer) == 8)
9996                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHL_IMM, offset_reg, src1->dreg, 3);
9997                                 else
9998                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHL_IMM, offset_reg, src1->dreg, 2);
9999
10000 #if SIZEOF_REGISTER == 8
10001                                 /* The upper word might not be zero, and we add it to a 64 bit address later */
10002                                 MONO_EMIT_NEW_UNALU (cfg, OP_ZEXT_I4, offset_reg, offset_reg);
10003 #endif
10004
10005                                 if (cfg->compile_aot) {
10006                                         MONO_EMIT_NEW_AOTCONST (cfg, table_reg, table, MONO_PATCH_INFO_SWITCH);
10007                                 } else {
10008                                         MONO_INST_NEW (cfg, ins, OP_JUMP_TABLE);
10009                                         ins->inst_c1 = MONO_PATCH_INFO_SWITCH;
10010                                         ins->inst_p0 = table;
10011                                         ins->dreg = table_reg;
10012                                         MONO_ADD_INS (cfg->cbb, ins);
10013                                 }
10014
10015                                 /* FIXME: Use load_memindex */
10016                                 MONO_EMIT_NEW_BIALU (cfg, OP_PADD, sum_reg, table_reg, offset_reg);
10017                                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, target_reg, sum_reg, 0);
10018                                 MONO_EMIT_NEW_UNALU (cfg, OP_BR_REG, -1, target_reg);
10019                         }
10020                         start_new_bblock = 1;
10021                         inline_costs += (BRANCH_COST * 2);
10022                         break;
10023                 }
10024                 case CEE_LDIND_I1:
10025                 case CEE_LDIND_U1:
10026                 case CEE_LDIND_I2:
10027                 case CEE_LDIND_U2:
10028                 case CEE_LDIND_I4:
10029                 case CEE_LDIND_U4:
10030                 case CEE_LDIND_I8:
10031                 case CEE_LDIND_I:
10032                 case CEE_LDIND_R4:
10033                 case CEE_LDIND_R8:
10034                 case CEE_LDIND_REF:
10035                         CHECK_STACK (1);
10036                         --sp;
10037
10038                         switch (*ip) {
10039                         case CEE_LDIND_R4:
10040                         case CEE_LDIND_R8:
10041                                 dreg = alloc_freg (cfg);
10042                                 break;
10043                         case CEE_LDIND_I8:
10044                                 dreg = alloc_lreg (cfg);
10045                                 break;
10046                         case CEE_LDIND_REF:
10047                                 dreg = alloc_ireg_ref (cfg);
10048                                 break;
10049                         default:
10050                                 dreg = alloc_preg (cfg);
10051                         }
10052
10053                         NEW_LOAD_MEMBASE (cfg, ins, ldind_to_load_membase (*ip), dreg, sp [0]->dreg, 0);
10054                         ins->type = ldind_type [*ip - CEE_LDIND_I1];
10055                         if (*ip == CEE_LDIND_R4)
10056                                 ins->type = cfg->r4_stack_type;
10057                         ins->flags |= ins_flag;
10058                         MONO_ADD_INS (cfg->cbb, ins);
10059                         *sp++ = ins;
10060                         if (ins_flag & MONO_INST_VOLATILE) {
10061                                 /* Volatile loads have acquire semantics, see 12.6.7 in Ecma 335 */
10062                                 emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_ACQ);
10063                         }
10064                         ins_flag = 0;
10065                         ++ip;
10066                         break;
10067                 case CEE_STIND_REF:
10068                 case CEE_STIND_I1:
10069                 case CEE_STIND_I2:
10070                 case CEE_STIND_I4:
10071                 case CEE_STIND_I8:
10072                 case CEE_STIND_R4:
10073                 case CEE_STIND_R8:
10074                 case CEE_STIND_I:
10075                         CHECK_STACK (2);
10076                         sp -= 2;
10077
10078                         if (ins_flag & MONO_INST_VOLATILE) {
10079                                 /* Volatile stores have release semantics, see 12.6.7 in Ecma 335 */
10080                                 emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL);
10081                         }
10082
10083                         NEW_STORE_MEMBASE (cfg, ins, stind_to_store_membase (*ip), sp [0]->dreg, 0, sp [1]->dreg);
10084                         ins->flags |= ins_flag;
10085                         ins_flag = 0;
10086
10087                         MONO_ADD_INS (cfg->cbb, ins);
10088
10089                         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)))
10090                                 emit_write_barrier (cfg, sp [0], sp [1]);
10091
10092                         inline_costs += 1;
10093                         ++ip;
10094                         break;
10095
10096                 case CEE_MUL:
10097                         CHECK_STACK (2);
10098
10099                         MONO_INST_NEW (cfg, ins, (*ip));
10100                         sp -= 2;
10101                         ins->sreg1 = sp [0]->dreg;
10102                         ins->sreg2 = sp [1]->dreg;
10103                         type_from_op (cfg, ins, sp [0], sp [1]);
10104                         CHECK_TYPE (ins);
10105                         ins->dreg = alloc_dreg ((cfg), (ins)->type);
10106
10107                         /* Use the immediate opcodes if possible */
10108                         if ((sp [1]->opcode == OP_ICONST) && mono_arch_is_inst_imm (sp [1]->inst_c0)) {
10109                                 int imm_opcode = mono_op_to_op_imm_noemul (ins->opcode);
10110                                 if (imm_opcode != -1) {
10111                                         ins->opcode = imm_opcode;
10112                                         ins->inst_p1 = (gpointer)(gssize)(sp [1]->inst_c0);
10113                                         ins->sreg2 = -1;
10114
10115                                         NULLIFY_INS (sp [1]);
10116                                 }
10117                         }
10118
10119                         MONO_ADD_INS ((cfg)->cbb, (ins));
10120
10121                         *sp++ = mono_decompose_opcode (cfg, ins);
10122                         ip++;
10123                         break;
10124                 case CEE_ADD:
10125                 case CEE_SUB:
10126                 case CEE_DIV:
10127                 case CEE_DIV_UN:
10128                 case CEE_REM:
10129                 case CEE_REM_UN:
10130                 case CEE_AND:
10131                 case CEE_OR:
10132                 case CEE_XOR:
10133                 case CEE_SHL:
10134                 case CEE_SHR:
10135                 case CEE_SHR_UN:
10136                         CHECK_STACK (2);
10137
10138                         MONO_INST_NEW (cfg, ins, (*ip));
10139                         sp -= 2;
10140                         ins->sreg1 = sp [0]->dreg;
10141                         ins->sreg2 = sp [1]->dreg;
10142                         type_from_op (cfg, ins, sp [0], sp [1]);
10143                         CHECK_TYPE (ins);
10144                         add_widen_op (cfg, ins, &sp [0], &sp [1]);
10145                         ins->dreg = alloc_dreg ((cfg), (ins)->type);
10146
10147                         /* FIXME: Pass opcode to is_inst_imm */
10148
10149                         /* Use the immediate opcodes if possible */
10150                         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)) {
10151                                 int imm_opcode;
10152
10153                                 imm_opcode = mono_op_to_op_imm_noemul (ins->opcode);
10154 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV)
10155                                 /* Keep emulated opcodes which are optimized away later */
10156                                 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) {
10157                                         imm_opcode = mono_op_to_op_imm (ins->opcode);
10158                                 }
10159 #endif
10160                                 if (imm_opcode != -1) {
10161                                         ins->opcode = imm_opcode;
10162                                         if (sp [1]->opcode == OP_I8CONST) {
10163 #if SIZEOF_REGISTER == 8
10164                                                 ins->inst_imm = sp [1]->inst_l;
10165 #else
10166                                                 ins->inst_ls_word = sp [1]->inst_ls_word;
10167                                                 ins->inst_ms_word = sp [1]->inst_ms_word;
10168 #endif
10169                                         }
10170                                         else
10171                                                 ins->inst_imm = (gssize)(sp [1]->inst_c0);
10172                                         ins->sreg2 = -1;
10173
10174                                         /* Might be followed by an instruction added by add_widen_op */
10175                                         if (sp [1]->next == NULL)
10176                                                 NULLIFY_INS (sp [1]);
10177                                 }
10178                         }
10179                         MONO_ADD_INS ((cfg)->cbb, (ins));
10180
10181                         *sp++ = mono_decompose_opcode (cfg, ins);
10182                         ip++;
10183                         break;
10184                 case CEE_NEG:
10185                 case CEE_NOT:
10186                 case CEE_CONV_I1:
10187                 case CEE_CONV_I2:
10188                 case CEE_CONV_I4:
10189                 case CEE_CONV_R4:
10190                 case CEE_CONV_R8:
10191                 case CEE_CONV_U4:
10192                 case CEE_CONV_I8:
10193                 case CEE_CONV_U8:
10194                 case CEE_CONV_OVF_I8:
10195                 case CEE_CONV_OVF_U8:
10196                 case CEE_CONV_R_UN:
10197                         CHECK_STACK (1);
10198
10199                         /* Special case this earlier so we have long constants in the IR */
10200                         if ((((*ip) == CEE_CONV_I8) || ((*ip) == CEE_CONV_U8)) && (sp [-1]->opcode == OP_ICONST)) {
10201                                 int data = sp [-1]->inst_c0;
10202                                 sp [-1]->opcode = OP_I8CONST;
10203                                 sp [-1]->type = STACK_I8;
10204 #if SIZEOF_REGISTER == 8
10205                                 if ((*ip) == CEE_CONV_U8)
10206                                         sp [-1]->inst_c0 = (guint32)data;
10207                                 else
10208                                         sp [-1]->inst_c0 = data;
10209 #else
10210                                 sp [-1]->inst_ls_word = data;
10211                                 if ((*ip) == CEE_CONV_U8)
10212                                         sp [-1]->inst_ms_word = 0;
10213                                 else
10214                                         sp [-1]->inst_ms_word = (data < 0) ? -1 : 0;
10215 #endif
10216                                 sp [-1]->dreg = alloc_dreg (cfg, STACK_I8);
10217                         }
10218                         else {
10219                                 ADD_UNOP (*ip);
10220                         }
10221                         ip++;
10222                         break;
10223                 case CEE_CONV_OVF_I4:
10224                 case CEE_CONV_OVF_I1:
10225                 case CEE_CONV_OVF_I2:
10226                 case CEE_CONV_OVF_I:
10227                 case CEE_CONV_OVF_U:
10228                         CHECK_STACK (1);
10229
10230                         if (sp [-1]->type == STACK_R8 || sp [-1]->type == STACK_R4) {
10231                                 ADD_UNOP (CEE_CONV_OVF_I8);
10232                                 ADD_UNOP (*ip);
10233                         } else {
10234                                 ADD_UNOP (*ip);
10235                         }
10236                         ip++;
10237                         break;
10238                 case CEE_CONV_OVF_U1:
10239                 case CEE_CONV_OVF_U2:
10240                 case CEE_CONV_OVF_U4:
10241                         CHECK_STACK (1);
10242
10243                         if (sp [-1]->type == STACK_R8 || sp [-1]->type == STACK_R4) {
10244                                 ADD_UNOP (CEE_CONV_OVF_U8);
10245                                 ADD_UNOP (*ip);
10246                         } else {
10247                                 ADD_UNOP (*ip);
10248                         }
10249                         ip++;
10250                         break;
10251                 case CEE_CONV_OVF_I1_UN:
10252                 case CEE_CONV_OVF_I2_UN:
10253                 case CEE_CONV_OVF_I4_UN:
10254                 case CEE_CONV_OVF_I8_UN:
10255                 case CEE_CONV_OVF_U1_UN:
10256                 case CEE_CONV_OVF_U2_UN:
10257                 case CEE_CONV_OVF_U4_UN:
10258                 case CEE_CONV_OVF_U8_UN:
10259                 case CEE_CONV_OVF_I_UN:
10260                 case CEE_CONV_OVF_U_UN:
10261                 case CEE_CONV_U2:
10262                 case CEE_CONV_U1:
10263                 case CEE_CONV_I:
10264                 case CEE_CONV_U:
10265                         CHECK_STACK (1);
10266                         ADD_UNOP (*ip);
10267                         CHECK_CFG_EXCEPTION;
10268                         ip++;
10269                         break;
10270                 case CEE_ADD_OVF:
10271                 case CEE_ADD_OVF_UN:
10272                 case CEE_MUL_OVF:
10273                 case CEE_MUL_OVF_UN:
10274                 case CEE_SUB_OVF:
10275                 case CEE_SUB_OVF_UN:
10276                         CHECK_STACK (2);
10277                         ADD_BINOP (*ip);
10278                         ip++;
10279                         break;
10280                 case CEE_CPOBJ:
10281                         GSHAREDVT_FAILURE (*ip);
10282                         CHECK_OPSIZE (5);
10283                         CHECK_STACK (2);
10284                         token = read32 (ip + 1);
10285                         klass = mini_get_class (method, token, generic_context);
10286                         CHECK_TYPELOAD (klass);
10287                         sp -= 2;
10288                         if (generic_class_is_reference_type (cfg, klass)) {
10289                                 MonoInst *store, *load;
10290                                 int dreg = alloc_ireg_ref (cfg);
10291
10292                                 NEW_LOAD_MEMBASE (cfg, load, OP_LOAD_MEMBASE, dreg, sp [1]->dreg, 0);
10293                                 load->flags |= ins_flag;
10294                                 MONO_ADD_INS (cfg->cbb, load);
10295
10296                                 NEW_STORE_MEMBASE (cfg, store, OP_STORE_MEMBASE_REG, sp [0]->dreg, 0, dreg);
10297                                 store->flags |= ins_flag;
10298                                 MONO_ADD_INS (cfg->cbb, store);
10299
10300                                 if (cfg->gen_write_barriers && cfg->method->wrapper_type != MONO_WRAPPER_WRITE_BARRIER)
10301                                         emit_write_barrier (cfg, sp [0], sp [1]);
10302                         } else {
10303                                 mini_emit_stobj (cfg, sp [0], sp [1], klass, FALSE);
10304                         }
10305                         ins_flag = 0;
10306                         ip += 5;
10307                         break;
10308                 case CEE_LDOBJ: {
10309                         int loc_index = -1;
10310                         int stloc_len = 0;
10311
10312                         CHECK_OPSIZE (5);
10313                         CHECK_STACK (1);
10314                         --sp;
10315                         token = read32 (ip + 1);
10316                         klass = mini_get_class (method, token, generic_context);
10317                         CHECK_TYPELOAD (klass);
10318
10319                         /* Optimize the common ldobj+stloc combination */
10320                         switch (ip [5]) {
10321                         case CEE_STLOC_S:
10322                                 loc_index = ip [6];
10323                                 stloc_len = 2;
10324                                 break;
10325                         case CEE_STLOC_0:
10326                         case CEE_STLOC_1:
10327                         case CEE_STLOC_2:
10328                         case CEE_STLOC_3:
10329                                 loc_index = ip [5] - CEE_STLOC_0;
10330                                 stloc_len = 1;
10331                                 break;
10332                         default:
10333                                 break;
10334                         }
10335
10336                         if ((loc_index != -1) && ip_in_bb (cfg, cfg->cbb, ip + 5)) {
10337                                 CHECK_LOCAL (loc_index);
10338
10339                                 EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, sp [0]->dreg, 0);
10340                                 ins->dreg = cfg->locals [loc_index]->dreg;
10341                                 ins->flags |= ins_flag;
10342                                 ip += 5;
10343                                 ip += stloc_len;
10344                                 if (ins_flag & MONO_INST_VOLATILE) {
10345                                         /* Volatile loads have acquire semantics, see 12.6.7 in Ecma 335 */
10346                                         emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_ACQ);
10347                                 }
10348                                 ins_flag = 0;
10349                                 break;
10350                         }
10351
10352                         /* Optimize the ldobj+stobj combination */
10353                         /* The reference case ends up being a load+store anyway */
10354                         /* Skip this if the operation is volatile. */
10355                         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)) {
10356                                 CHECK_STACK (1);
10357
10358                                 sp --;
10359
10360                                 mini_emit_stobj (cfg, sp [0], sp [1], klass, FALSE);
10361
10362                                 ip += 5 + 5;
10363                                 ins_flag = 0;
10364                                 break;
10365                         }
10366
10367                         EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, sp [0]->dreg, 0);
10368                         ins->flags |= ins_flag;
10369                         *sp++ = ins;
10370
10371                         if (ins_flag & MONO_INST_VOLATILE) {
10372                                 /* Volatile loads have acquire semantics, see 12.6.7 in Ecma 335 */
10373                                 emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_ACQ);
10374                         }
10375
10376                         ip += 5;
10377                         ins_flag = 0;
10378                         inline_costs += 1;
10379                         break;
10380                 }
10381                 case CEE_LDSTR:
10382                         CHECK_STACK_OVF (1);
10383                         CHECK_OPSIZE (5);
10384                         n = read32 (ip + 1);
10385
10386                         if (method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD) {
10387                                 EMIT_NEW_PCONST (cfg, ins, mono_method_get_wrapper_data (method, n));
10388                                 ins->type = STACK_OBJ;
10389                                 *sp = ins;
10390                         }
10391                         else if (method->wrapper_type != MONO_WRAPPER_NONE) {
10392                                 MonoInst *iargs [1];
10393                                 char *str = mono_method_get_wrapper_data (method, n);
10394
10395                                 if (cfg->compile_aot)
10396                                         EMIT_NEW_LDSTRLITCONST (cfg, iargs [0], str);
10397                                 else
10398                                         EMIT_NEW_PCONST (cfg, iargs [0], str);
10399                                 *sp = mono_emit_jit_icall (cfg, mono_string_new_wrapper, iargs);
10400                         } else {
10401                                 if (cfg->opt & MONO_OPT_SHARED) {
10402                                         MonoInst *iargs [3];
10403
10404                                         if (cfg->compile_aot) {
10405                                                 cfg->ldstr_list = g_list_prepend (cfg->ldstr_list, GINT_TO_POINTER (n));
10406                                         }
10407                                         EMIT_NEW_DOMAINCONST (cfg, iargs [0]);
10408                                         EMIT_NEW_IMAGECONST (cfg, iargs [1], image);
10409                                         EMIT_NEW_ICONST (cfg, iargs [2], mono_metadata_token_index (n));
10410                                         *sp = mono_emit_jit_icall (cfg, mono_ldstr, iargs);
10411                                         mono_ldstr (cfg->domain, image, mono_metadata_token_index (n));
10412                                 } else {
10413                                         if (cfg->cbb->out_of_line) {
10414                                                 MonoInst *iargs [2];
10415
10416                                                 if (image == mono_defaults.corlib) {
10417                                                         /* 
10418                                                          * Avoid relocations in AOT and save some space by using a 
10419                                                          * version of helper_ldstr specialized to mscorlib.
10420                                                          */
10421                                                         EMIT_NEW_ICONST (cfg, iargs [0], mono_metadata_token_index (n));
10422                                                         *sp = mono_emit_jit_icall (cfg, mono_helper_ldstr_mscorlib, iargs);
10423                                                 } else {
10424                                                         /* Avoid creating the string object */
10425                                                         EMIT_NEW_IMAGECONST (cfg, iargs [0], image);
10426                                                         EMIT_NEW_ICONST (cfg, iargs [1], mono_metadata_token_index (n));
10427                                                         *sp = mono_emit_jit_icall (cfg, mono_helper_ldstr, iargs);
10428                                                 }
10429                                         } 
10430                                         else
10431                                         if (cfg->compile_aot) {
10432                                                 NEW_LDSTRCONST (cfg, ins, image, n);
10433                                                 *sp = ins;
10434                                                 MONO_ADD_INS (cfg->cbb, ins);
10435                                         } 
10436                                         else {
10437                                                 NEW_PCONST (cfg, ins, NULL);
10438                                                 ins->type = STACK_OBJ;
10439                                                 ins->inst_p0 = mono_ldstr (cfg->domain, image, mono_metadata_token_index (n));
10440                                                 if (!ins->inst_p0)
10441                                                         OUT_OF_MEMORY_FAILURE;
10442
10443                                                 *sp = ins;
10444                                                 MONO_ADD_INS (cfg->cbb, ins);
10445                                         }
10446                                 }
10447                         }
10448
10449                         sp++;
10450                         ip += 5;
10451                         break;
10452                 case CEE_NEWOBJ: {
10453                         MonoInst *iargs [2];
10454                         MonoMethodSignature *fsig;
10455                         MonoInst this_ins;
10456                         MonoInst *alloc;
10457                         MonoInst *vtable_arg = NULL;
10458
10459                         CHECK_OPSIZE (5);
10460                         token = read32 (ip + 1);
10461                         cmethod = mini_get_method (cfg, method, token, NULL, generic_context);
10462                         if (!cmethod || mono_loader_get_last_error ())
10463                                 LOAD_ERROR;
10464                         fsig = mono_method_get_signature_checked (cmethod, image, token, generic_context, &cfg->error);
10465                         CHECK_CFG_ERROR;
10466
10467                         mono_save_token_info (cfg, image, token, cmethod);
10468
10469                         if (!mono_class_init (cmethod->klass))
10470                                 TYPE_LOAD_ERROR (cmethod->klass);
10471
10472                         context_used = mini_method_check_context_used (cfg, cmethod);
10473
10474                         if (mono_security_core_clr_enabled ())
10475                                 ensure_method_is_allowed_to_call_method (cfg, method, cmethod);
10476
10477                         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)) {
10478                                 emit_class_init (cfg, cmethod->klass);
10479                                 CHECK_TYPELOAD (cmethod->klass);
10480                         }
10481
10482                         /*
10483                         if (cfg->gsharedvt) {
10484                                 if (mini_is_gsharedvt_variable_signature (sig))
10485                                         GSHAREDVT_FAILURE (*ip);
10486                         }
10487                         */
10488
10489                         n = fsig->param_count;
10490                         CHECK_STACK (n);
10491
10492                         /* 
10493                          * Generate smaller code for the common newobj <exception> instruction in
10494                          * argument checking code.
10495                          */
10496                         if (cfg->cbb->out_of_line && cmethod->klass->image == mono_defaults.corlib &&
10497                                 is_exception_class (cmethod->klass) && n <= 2 &&
10498                                 ((n < 1) || (!fsig->params [0]->byref && fsig->params [0]->type == MONO_TYPE_STRING)) && 
10499                                 ((n < 2) || (!fsig->params [1]->byref && fsig->params [1]->type == MONO_TYPE_STRING))) {
10500                                 MonoInst *iargs [3];
10501
10502                                 sp -= n;
10503
10504                                 EMIT_NEW_ICONST (cfg, iargs [0], cmethod->klass->type_token);
10505                                 switch (n) {
10506                                 case 0:
10507                                         *sp ++ = mono_emit_jit_icall (cfg, mono_create_corlib_exception_0, iargs);
10508                                         break;
10509                                 case 1:
10510                                         iargs [1] = sp [0];
10511                                         *sp ++ = mono_emit_jit_icall (cfg, mono_create_corlib_exception_1, iargs);
10512                                         break;
10513                                 case 2:
10514                                         iargs [1] = sp [0];
10515                                         iargs [2] = sp [1];
10516                                         *sp ++ = mono_emit_jit_icall (cfg, mono_create_corlib_exception_2, iargs);
10517                                         break;
10518                                 default:
10519                                         g_assert_not_reached ();
10520                                 }
10521
10522                                 ip += 5;
10523                                 inline_costs += 5;
10524                                 break;
10525                         }
10526
10527                         /* move the args to allow room for 'this' in the first position */
10528                         while (n--) {
10529                                 --sp;
10530                                 sp [1] = sp [0];
10531                         }
10532
10533                         /* check_call_signature () requires sp[0] to be set */
10534                         this_ins.type = STACK_OBJ;
10535                         sp [0] = &this_ins;
10536                         if (check_call_signature (cfg, fsig, sp))
10537                                 UNVERIFIED;
10538
10539                         iargs [0] = NULL;
10540
10541                         if (mini_class_is_system_array (cmethod->klass)) {
10542                                 *sp = emit_get_rgctx_method (cfg, context_used,
10543                                                                                          cmethod, MONO_RGCTX_INFO_METHOD);
10544
10545                                 /* Avoid varargs in the common case */
10546                                 if (fsig->param_count == 1)
10547                                         alloc = mono_emit_jit_icall (cfg, mono_array_new_1, sp);
10548                                 else if (fsig->param_count == 2)
10549                                         alloc = mono_emit_jit_icall (cfg, mono_array_new_2, sp);
10550                                 else if (fsig->param_count == 3)
10551                                         alloc = mono_emit_jit_icall (cfg, mono_array_new_3, sp);
10552                                 else if (fsig->param_count == 4)
10553                                         alloc = mono_emit_jit_icall (cfg, mono_array_new_4, sp);
10554                                 else
10555                                         alloc = handle_array_new (cfg, fsig->param_count, sp, ip);
10556                         } else if (cmethod->string_ctor) {
10557                                 g_assert (!context_used);
10558                                 g_assert (!vtable_arg);
10559                                 /* we simply pass a null pointer */
10560                                 EMIT_NEW_PCONST (cfg, *sp, NULL); 
10561                                 /* now call the string ctor */
10562                                 alloc = mono_emit_method_call_full (cfg, cmethod, fsig, FALSE, sp, NULL, NULL, NULL);
10563                         } else {
10564                                 if (cmethod->klass->valuetype) {
10565                                         iargs [0] = mono_compile_create_var (cfg, &cmethod->klass->byval_arg, OP_LOCAL);
10566                                         emit_init_rvar (cfg, iargs [0]->dreg, &cmethod->klass->byval_arg);
10567                                         EMIT_NEW_TEMPLOADA (cfg, *sp, iargs [0]->inst_c0);
10568
10569                                         alloc = NULL;
10570
10571                                         /* 
10572                                          * The code generated by mini_emit_virtual_call () expects
10573                                          * iargs [0] to be a boxed instance, but luckily the vcall
10574                                          * will be transformed into a normal call there.
10575                                          */
10576                                 } else if (context_used) {
10577                                         alloc = handle_alloc (cfg, cmethod->klass, FALSE, context_used);
10578                                         *sp = alloc;
10579                                 } else {
10580                                         MonoVTable *vtable = NULL;
10581
10582                                         if (!cfg->compile_aot)
10583                                                 vtable = mono_class_vtable (cfg->domain, cmethod->klass);
10584                                         CHECK_TYPELOAD (cmethod->klass);
10585
10586                                         /*
10587                                          * TypeInitializationExceptions thrown from the mono_runtime_class_init
10588                                          * call in mono_jit_runtime_invoke () can abort the finalizer thread.
10589                                          * As a workaround, we call class cctors before allocating objects.
10590                                          */
10591                                         if (mini_field_access_needs_cctor_run (cfg, method, cmethod->klass, vtable) && !(g_slist_find (class_inits, cmethod->klass))) {
10592                                                 emit_class_init (cfg, cmethod->klass);
10593                                                 if (cfg->verbose_level > 2)
10594                                                         printf ("class %s.%s needs init call for ctor\n", cmethod->klass->name_space, cmethod->klass->name);
10595                                                 class_inits = g_slist_prepend (class_inits, cmethod->klass);
10596                                         }
10597
10598                                         alloc = handle_alloc (cfg, cmethod->klass, FALSE, 0);
10599                                         *sp = alloc;
10600                                 }
10601                                 CHECK_CFG_EXCEPTION; /*for handle_alloc*/
10602
10603                                 if (alloc)
10604                                         MONO_EMIT_NEW_UNALU (cfg, OP_NOT_NULL, -1, alloc->dreg);
10605
10606                                 /* Now call the actual ctor */
10607                                 handle_ctor_call (cfg, cmethod, fsig, context_used, sp, ip, &inline_costs);
10608                                 CHECK_CFG_EXCEPTION;
10609                         }
10610
10611                         if (alloc == NULL) {
10612                                 /* Valuetype */
10613                                 EMIT_NEW_TEMPLOAD (cfg, ins, iargs [0]->inst_c0);
10614                                 type_to_eval_stack_type (cfg, &ins->klass->byval_arg, ins);
10615                                 *sp++= ins;
10616                         } else {
10617                                 *sp++ = alloc;
10618                         }
10619                         
10620                         ip += 5;
10621                         inline_costs += 5;
10622                         if (!(seq_point_locs && mono_bitset_test_fast (seq_point_locs, ip - header->code)))
10623                                 emit_seq_point (cfg, method, ip, FALSE, TRUE);
10624                         break;
10625                 }
10626                 case CEE_CASTCLASS:
10627                         CHECK_STACK (1);
10628                         --sp;
10629                         CHECK_OPSIZE (5);
10630                         token = read32 (ip + 1);
10631                         klass = mini_get_class (method, token, generic_context);
10632                         CHECK_TYPELOAD (klass);
10633                         if (sp [0]->type != STACK_OBJ)
10634                                 UNVERIFIED;
10635
10636                         ins = handle_castclass (cfg, klass, *sp, ip, &inline_costs);
10637                         CHECK_CFG_EXCEPTION;
10638
10639                         *sp ++ = ins;
10640                         ip += 5;
10641                         break;
10642                 case CEE_ISINST: {
10643                         CHECK_STACK (1);
10644                         --sp;
10645                         CHECK_OPSIZE (5);
10646                         token = read32 (ip + 1);
10647                         klass = mini_get_class (method, token, generic_context);
10648                         CHECK_TYPELOAD (klass);
10649                         if (sp [0]->type != STACK_OBJ)
10650                                 UNVERIFIED;
10651  
10652                         context_used = mini_class_check_context_used (cfg, klass);
10653
10654                         if (!context_used && mini_class_has_reference_variant_generic_argument (cfg, klass, context_used)) {
10655                                 MonoMethod *mono_isinst = mono_marshal_get_isinst_with_cache ();
10656                                 MonoInst *args [3];
10657                                 int idx;
10658
10659                                 /* obj */
10660                                 args [0] = *sp;
10661
10662                                 /* klass */
10663                                 EMIT_NEW_CLASSCONST (cfg, args [1], klass);
10664
10665                                 /* inline cache*/
10666                                 if (cfg->compile_aot) {
10667                                         idx = get_castclass_cache_idx (cfg);
10668                                         EMIT_NEW_AOTCONST (cfg, args [2], MONO_PATCH_INFO_CASTCLASS_CACHE, GINT_TO_POINTER (idx));
10669                                 } else {
10670                                         EMIT_NEW_PCONST (cfg, args [2], mono_domain_alloc0 (cfg->domain, sizeof (gpointer)));
10671                                 }
10672
10673                                 *sp++ = mono_emit_method_call (cfg, mono_isinst, args, NULL);
10674                                 ip += 5;
10675                                 inline_costs += 2;
10676                         } else if (!context_used && (mono_class_is_marshalbyref (klass) || klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
10677                                 MonoMethod *mono_isinst;
10678                                 MonoInst *iargs [1];
10679                                 int costs;
10680
10681                                 mono_isinst = mono_marshal_get_isinst (klass); 
10682                                 iargs [0] = sp [0];
10683
10684                                 costs = inline_method (cfg, mono_isinst, mono_method_signature (mono_isinst), 
10685                                                                            iargs, ip, cfg->real_offset, TRUE);
10686                                 CHECK_CFG_EXCEPTION;
10687                                 g_assert (costs > 0);
10688                                 
10689                                 ip += 5;
10690                                 cfg->real_offset += 5;
10691
10692                                 *sp++= iargs [0];
10693
10694                                 inline_costs += costs;
10695                         }
10696                         else {
10697                                 ins = handle_isinst (cfg, klass, *sp, context_used);
10698                                 CHECK_CFG_EXCEPTION;
10699                                 *sp ++ = ins;
10700                                 ip += 5;
10701                         }
10702                         break;
10703                 }
10704                 case CEE_UNBOX_ANY: {
10705                         MonoInst *res, *addr;
10706
10707                         CHECK_STACK (1);
10708                         --sp;
10709                         CHECK_OPSIZE (5);
10710                         token = read32 (ip + 1);
10711                         klass = mini_get_class (method, token, generic_context);
10712                         CHECK_TYPELOAD (klass);
10713
10714                         mono_save_token_info (cfg, image, token, klass);
10715
10716                         context_used = mini_class_check_context_used (cfg, klass);
10717
10718                         if (mini_is_gsharedvt_klass (klass)) {
10719                                 res = handle_unbox_gsharedvt (cfg, klass, *sp);
10720                                 inline_costs += 2;
10721                         } else if (generic_class_is_reference_type (cfg, klass)) {
10722                                 res = handle_castclass (cfg, klass, *sp, ip, &inline_costs);
10723                                 CHECK_CFG_EXCEPTION;
10724                         } else if (mono_class_is_nullable (klass)) {
10725                                 res = handle_unbox_nullable (cfg, *sp, klass, context_used);
10726                         } else {
10727                                 addr = handle_unbox (cfg, klass, sp, context_used);
10728                                 /* LDOBJ */
10729                                 EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, addr->dreg, 0);
10730                                 res = ins;
10731                                 inline_costs += 2;
10732                         }
10733
10734                         *sp ++ = res;
10735                         ip += 5;
10736                         break;
10737                 }
10738                 case CEE_BOX: {
10739                         MonoInst *val;
10740                         MonoClass *enum_class;
10741                         MonoMethod *has_flag;
10742
10743                         CHECK_STACK (1);
10744                         --sp;
10745                         val = *sp;
10746                         CHECK_OPSIZE (5);
10747                         token = read32 (ip + 1);
10748                         klass = mini_get_class (method, token, generic_context);
10749                         CHECK_TYPELOAD (klass);
10750
10751                         mono_save_token_info (cfg, image, token, klass);
10752
10753                         context_used = mini_class_check_context_used (cfg, klass);
10754
10755                         if (generic_class_is_reference_type (cfg, klass)) {
10756                                 *sp++ = val;
10757                                 ip += 5;
10758                                 break;
10759                         }
10760
10761                         if (klass == mono_defaults.void_class)
10762                                 UNVERIFIED;
10763                         if (target_type_is_incompatible (cfg, &klass->byval_arg, *sp))
10764                                 UNVERIFIED;
10765                         /* frequent check in generic code: box (struct), brtrue */
10766
10767                         /*
10768                          * Look for:
10769                          *
10770                          *   <push int/long ptr>
10771                          *   <push int/long>
10772                          *   box MyFlags
10773                          *   constrained. MyFlags
10774                          *   callvirt instace bool class [mscorlib] System.Enum::HasFlag (class [mscorlib] System.Enum)
10775                          *
10776                          * If we find this sequence and the operand types on box and constrained
10777                          * are equal, we can emit a specialized instruction sequence instead of
10778                          * the very slow HasFlag () call.
10779                          */
10780                         if ((cfg->opt & MONO_OPT_INTRINS) &&
10781                             /* Cheap checks first. */
10782                             ip + 5 + 6 + 5 < end &&
10783                             ip [5] == CEE_PREFIX1 &&
10784                             ip [6] == CEE_CONSTRAINED_ &&
10785                             ip [11] == CEE_CALLVIRT &&
10786                             ip_in_bb (cfg, cfg->cbb, ip + 5 + 6 + 5) &&
10787                             mono_class_is_enum (klass) &&
10788                             (enum_class = mini_get_class (method, read32 (ip + 7), generic_context)) &&
10789                             (has_flag = mini_get_method (cfg, method, read32 (ip + 12), NULL, generic_context)) &&
10790                             has_flag->klass == mono_defaults.enum_class &&
10791                             !strcmp (has_flag->name, "HasFlag") &&
10792                             has_flag->signature->hasthis &&
10793                             has_flag->signature->param_count == 1) {
10794                                 CHECK_TYPELOAD (enum_class);
10795
10796                                 if (enum_class == klass) {
10797                                         MonoInst *enum_this, *enum_flag;
10798
10799                                         ip += 5 + 6 + 5;
10800                                         --sp;
10801
10802                                         enum_this = sp [0];
10803                                         enum_flag = sp [1];
10804
10805                                         *sp++ = handle_enum_has_flag (cfg, klass, enum_this, enum_flag);
10806                                         break;
10807                                 }
10808                         }
10809
10810                         // FIXME: LLVM can't handle the inconsistent bb linking
10811                         if (!mono_class_is_nullable (klass) &&
10812                                 !mini_is_gsharedvt_klass (klass) &&
10813                                 ip + 5 < end && ip_in_bb (cfg, cfg->cbb, ip + 5) &&
10814                                 (ip [5] == CEE_BRTRUE || 
10815                                  ip [5] == CEE_BRTRUE_S ||
10816                                  ip [5] == CEE_BRFALSE ||
10817                                  ip [5] == CEE_BRFALSE_S)) {
10818                                 gboolean is_true = ip [5] == CEE_BRTRUE || ip [5] == CEE_BRTRUE_S;
10819                                 int dreg;
10820                                 MonoBasicBlock *true_bb, *false_bb;
10821
10822                                 ip += 5;
10823
10824                                 if (cfg->verbose_level > 3) {
10825                                         printf ("converting (in B%d: stack: %d) %s", cfg->cbb->block_num, (int)(sp - stack_start), mono_disasm_code_one (NULL, method, ip, NULL));
10826                                         printf ("<box+brtrue opt>\n");
10827                                 }
10828
10829                                 switch (*ip) {
10830                                 case CEE_BRTRUE_S:
10831                                 case CEE_BRFALSE_S:
10832                                         CHECK_OPSIZE (2);
10833                                         ip++;
10834                                         target = ip + 1 + (signed char)(*ip);
10835                                         ip++;
10836                                         break;
10837                                 case CEE_BRTRUE:
10838                                 case CEE_BRFALSE:
10839                                         CHECK_OPSIZE (5);
10840                                         ip++;
10841                                         target = ip + 4 + (gint)(read32 (ip));
10842                                         ip += 4;
10843                                         break;
10844                                 default:
10845                                         g_assert_not_reached ();
10846                                 }
10847
10848                                 /* 
10849                                  * We need to link both bblocks, since it is needed for handling stack
10850                                  * arguments correctly (See test_0_box_brtrue_opt_regress_81102).
10851                                  * Branching to only one of them would lead to inconsistencies, so
10852                                  * generate an ICONST+BRTRUE, the branch opts will get rid of them.
10853                                  */
10854                                 GET_BBLOCK (cfg, true_bb, target);
10855                                 GET_BBLOCK (cfg, false_bb, ip);
10856
10857                                 mono_link_bblock (cfg, cfg->cbb, true_bb);
10858                                 mono_link_bblock (cfg, cfg->cbb, false_bb);
10859
10860                                 if (sp != stack_start) {
10861                                         handle_stack_args (cfg, stack_start, sp - stack_start);
10862                                         sp = stack_start;
10863                                         CHECK_UNVERIFIABLE (cfg);
10864                                 }
10865
10866                                 if (COMPILE_LLVM (cfg)) {
10867                                         dreg = alloc_ireg (cfg);
10868                                         MONO_EMIT_NEW_ICONST (cfg, dreg, 0);
10869                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, dreg, is_true ? 0 : 1);
10870
10871                                         MONO_EMIT_NEW_BRANCH_BLOCK2 (cfg, OP_IBEQ, true_bb, false_bb);
10872                                 } else {
10873                                         /* The JIT can't eliminate the iconst+compare */
10874                                         MONO_INST_NEW (cfg, ins, OP_BR);
10875                                         ins->inst_target_bb = is_true ? true_bb : false_bb;
10876                                         MONO_ADD_INS (cfg->cbb, ins);
10877                                 }
10878
10879                                 start_new_bblock = 1;
10880                                 break;
10881                         }
10882
10883                         *sp++ = handle_box (cfg, val, klass, context_used);
10884
10885                         CHECK_CFG_EXCEPTION;
10886                         ip += 5;
10887                         inline_costs += 1;
10888                         break;
10889                 }
10890                 case CEE_UNBOX: {
10891                         CHECK_STACK (1);
10892                         --sp;
10893                         CHECK_OPSIZE (5);
10894                         token = read32 (ip + 1);
10895                         klass = mini_get_class (method, token, generic_context);
10896                         CHECK_TYPELOAD (klass);
10897
10898                         mono_save_token_info (cfg, image, token, klass);
10899
10900                         context_used = mini_class_check_context_used (cfg, klass);
10901
10902                         if (mono_class_is_nullable (klass)) {
10903                                 MonoInst *val;
10904
10905                                 val = handle_unbox_nullable (cfg, *sp, klass, context_used);
10906                                 EMIT_NEW_VARLOADA (cfg, ins, get_vreg_to_inst (cfg, val->dreg), &val->klass->byval_arg);
10907
10908                                 *sp++= ins;
10909                         } else {
10910                                 ins = handle_unbox (cfg, klass, sp, context_used);
10911                                 *sp++ = ins;
10912                         }
10913                         ip += 5;
10914                         inline_costs += 2;
10915                         break;
10916                 }
10917                 case CEE_LDFLD:
10918                 case CEE_LDFLDA:
10919                 case CEE_STFLD:
10920                 case CEE_LDSFLD:
10921                 case CEE_LDSFLDA:
10922                 case CEE_STSFLD: {
10923                         MonoClassField *field;
10924 #ifndef DISABLE_REMOTING
10925                         int costs;
10926 #endif
10927                         guint foffset;
10928                         gboolean is_instance;
10929                         int op;
10930                         gpointer addr = NULL;
10931                         gboolean is_special_static;
10932                         MonoType *ftype;
10933                         MonoInst *store_val = NULL;
10934                         MonoInst *thread_ins;
10935
10936                         op = *ip;
10937                         is_instance = (op == CEE_LDFLD || op == CEE_LDFLDA || op == CEE_STFLD);
10938                         if (is_instance) {
10939                                 if (op == CEE_STFLD) {
10940                                         CHECK_STACK (2);
10941                                         sp -= 2;
10942                                         store_val = sp [1];
10943                                 } else {
10944                                         CHECK_STACK (1);
10945                                         --sp;
10946                                 }
10947                                 if (sp [0]->type == STACK_I4 || sp [0]->type == STACK_I8 || sp [0]->type == STACK_R8)
10948                                         UNVERIFIED;
10949                                 if (*ip != CEE_LDFLD && sp [0]->type == STACK_VTYPE)
10950                                         UNVERIFIED;
10951                         } else {
10952                                 if (op == CEE_STSFLD) {
10953                                         CHECK_STACK (1);
10954                                         sp--;
10955                                         store_val = sp [0];
10956                                 }
10957                         }
10958
10959                         CHECK_OPSIZE (5);
10960                         token = read32 (ip + 1);
10961                         if (method->wrapper_type != MONO_WRAPPER_NONE) {
10962                                 field = mono_method_get_wrapper_data (method, token);
10963                                 klass = field->parent;
10964                         }
10965                         else {
10966                                 field = mono_field_from_token_checked (image, token, &klass, generic_context, &cfg->error);
10967                                 CHECK_CFG_ERROR;
10968                         }
10969                         if (!dont_verify && !cfg->skip_visibility && !mono_method_can_access_field (method, field))
10970                                 FIELD_ACCESS_FAILURE (method, field);
10971                         mono_class_init (klass);
10972
10973                         /* if the class is Critical then transparent code cannot access it's fields */
10974                         if (!is_instance && mono_security_core_clr_enabled ())
10975                                 ensure_method_is_allowed_to_access_field (cfg, method, field);
10976
10977                         /* XXX this is technically required but, so far (SL2), no [SecurityCritical] types (not many exists) have
10978                            any visible *instance* field  (in fact there's a single case for a static field in Marshal) XXX
10979                         if (mono_security_core_clr_enabled ())
10980                                 ensure_method_is_allowed_to_access_field (cfg, method, field);
10981                         */
10982
10983                         ftype = mono_field_get_type (field);
10984
10985                         /*
10986                          * LDFLD etc. is usable on static fields as well, so convert those cases to
10987                          * the static case.
10988                          */
10989                         if (is_instance && ftype->attrs & FIELD_ATTRIBUTE_STATIC) {
10990                                 switch (op) {
10991                                 case CEE_LDFLD:
10992                                         op = CEE_LDSFLD;
10993                                         break;
10994                                 case CEE_STFLD:
10995                                         op = CEE_STSFLD;
10996                                         break;
10997                                 case CEE_LDFLDA:
10998                                         op = CEE_LDSFLDA;
10999                                         break;
11000                                 default:
11001                                         g_assert_not_reached ();
11002                                 }
11003                                 is_instance = FALSE;
11004                         }
11005
11006                         context_used = mini_class_check_context_used (cfg, klass);
11007
11008                         /* INSTANCE CASE */
11009
11010                         foffset = klass->valuetype? field->offset - sizeof (MonoObject): field->offset;
11011                         if (op == CEE_STFLD) {
11012                                 if (target_type_is_incompatible (cfg, field->type, sp [1]))
11013                                         UNVERIFIED;
11014 #ifndef DISABLE_REMOTING
11015                                 if ((mono_class_is_marshalbyref (klass) && !MONO_CHECK_THIS (sp [0])) || mono_class_is_contextbound (klass) || klass == mono_defaults.marshalbyrefobject_class) {
11016                                         MonoMethod *stfld_wrapper = mono_marshal_get_stfld_wrapper (field->type); 
11017                                         MonoInst *iargs [5];
11018
11019                                         GSHAREDVT_FAILURE (op);
11020
11021                                         iargs [0] = sp [0];
11022                                         EMIT_NEW_CLASSCONST (cfg, iargs [1], klass);
11023                                         EMIT_NEW_FIELDCONST (cfg, iargs [2], field);
11024                                         EMIT_NEW_ICONST (cfg, iargs [3], klass->valuetype ? field->offset - sizeof (MonoObject) : 
11025                                                     field->offset);
11026                                         iargs [4] = sp [1];
11027
11028                                         if (cfg->opt & MONO_OPT_INLINE || cfg->compile_aot) {
11029                                                 costs = inline_method (cfg, stfld_wrapper, mono_method_signature (stfld_wrapper), 
11030                                                                                            iargs, ip, cfg->real_offset, TRUE);
11031                                                 CHECK_CFG_EXCEPTION;
11032                                                 g_assert (costs > 0);
11033                                                       
11034                                                 cfg->real_offset += 5;
11035
11036                                                 inline_costs += costs;
11037                                         } else {
11038                                                 mono_emit_method_call (cfg, stfld_wrapper, iargs, NULL);
11039                                         }
11040                                 } else
11041 #endif
11042                                 {
11043                                         MonoInst *store;
11044
11045                                         MONO_EMIT_NULL_CHECK (cfg, sp [0]->dreg);
11046
11047                                         if (mini_is_gsharedvt_klass (klass)) {
11048                                                 MonoInst *offset_ins;
11049
11050                                                 context_used = mini_class_check_context_used (cfg, klass);
11051
11052                                                 offset_ins = emit_get_gsharedvt_info (cfg, field, MONO_RGCTX_INFO_FIELD_OFFSET);
11053                                                 dreg = alloc_ireg_mp (cfg);
11054                                                 EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, sp [0]->dreg, offset_ins->dreg);
11055                                                 /* The decomposition will call mini_emit_stobj () which will emit a wbarrier if needed */
11056                                                 EMIT_NEW_STORE_MEMBASE_TYPE (cfg, store, field->type, dreg, 0, sp [1]->dreg);
11057                                         } else {
11058                                                 EMIT_NEW_STORE_MEMBASE_TYPE (cfg, store, field->type, sp [0]->dreg, foffset, sp [1]->dreg);
11059                                         }
11060                                         if (sp [0]->opcode != OP_LDADDR)
11061                                                 store->flags |= MONO_INST_FAULT;
11062
11063                                 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)) {
11064                                         /* insert call to write barrier */
11065                                         MonoInst *ptr;
11066                                         int dreg;
11067
11068                                         dreg = alloc_ireg_mp (cfg);
11069                                         EMIT_NEW_BIALU_IMM (cfg, ptr, OP_PADD_IMM, dreg, sp [0]->dreg, foffset);
11070                                         emit_write_barrier (cfg, ptr, sp [1]);
11071                                 }
11072
11073                                         store->flags |= ins_flag;
11074                                 }
11075                                 ins_flag = 0;
11076                                 ip += 5;
11077                                 break;
11078                         }
11079
11080 #ifndef DISABLE_REMOTING
11081                         if (is_instance && ((mono_class_is_marshalbyref (klass) && !MONO_CHECK_THIS (sp [0])) || mono_class_is_contextbound (klass) || klass == mono_defaults.marshalbyrefobject_class)) {
11082                                 MonoMethod *wrapper = (op == CEE_LDFLDA) ? mono_marshal_get_ldflda_wrapper (field->type) : mono_marshal_get_ldfld_wrapper (field->type); 
11083                                 MonoInst *iargs [4];
11084
11085                                 GSHAREDVT_FAILURE (op);
11086
11087                                 iargs [0] = sp [0];
11088                                 EMIT_NEW_CLASSCONST (cfg, iargs [1], klass);
11089                                 EMIT_NEW_FIELDCONST (cfg, iargs [2], field);
11090                                 EMIT_NEW_ICONST (cfg, iargs [3], klass->valuetype ? field->offset - sizeof (MonoObject) : field->offset);
11091                                 if (cfg->opt & MONO_OPT_INLINE || cfg->compile_aot) {
11092                                         costs = inline_method (cfg, wrapper, mono_method_signature (wrapper), 
11093                                                                                    iargs, ip, cfg->real_offset, TRUE);
11094                                         CHECK_CFG_EXCEPTION;
11095                                         g_assert (costs > 0);
11096                                                       
11097                                         cfg->real_offset += 5;
11098
11099                                         *sp++ = iargs [0];
11100
11101                                         inline_costs += costs;
11102                                 } else {
11103                                         ins = mono_emit_method_call (cfg, wrapper, iargs, NULL);
11104                                         *sp++ = ins;
11105                                 }
11106                         } else 
11107 #endif
11108                         if (is_instance) {
11109                                 if (sp [0]->type == STACK_VTYPE) {
11110                                         MonoInst *var;
11111
11112                                         /* Have to compute the address of the variable */
11113
11114                                         var = get_vreg_to_inst (cfg, sp [0]->dreg);
11115                                         if (!var)
11116                                                 var = mono_compile_create_var_for_vreg (cfg, &klass->byval_arg, OP_LOCAL, sp [0]->dreg);
11117                                         else
11118                                                 g_assert (var->klass == klass);
11119                                         
11120                                         EMIT_NEW_VARLOADA (cfg, ins, var, &var->klass->byval_arg);
11121                                         sp [0] = ins;
11122                                 }
11123
11124                                 if (op == CEE_LDFLDA) {
11125                                         if (sp [0]->type == STACK_OBJ) {
11126                                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, sp [0]->dreg, 0);
11127                                                 MONO_EMIT_NEW_COND_EXC (cfg, EQ, "NullReferenceException");
11128                                         }
11129
11130                                         dreg = alloc_ireg_mp (cfg);
11131
11132                                         if (mini_is_gsharedvt_klass (klass)) {
11133                                                 MonoInst *offset_ins;
11134
11135                                                 offset_ins = emit_get_gsharedvt_info (cfg, field, MONO_RGCTX_INFO_FIELD_OFFSET);
11136                                                 EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, sp [0]->dreg, offset_ins->dreg);
11137                                         } else {
11138                                                 EMIT_NEW_BIALU_IMM (cfg, ins, OP_PADD_IMM, dreg, sp [0]->dreg, foffset);
11139                                         }
11140                                         ins->klass = mono_class_from_mono_type (field->type);
11141                                         ins->type = STACK_MP;
11142                                         *sp++ = ins;
11143                                 } else {
11144                                         MonoInst *load;
11145
11146                                         MONO_EMIT_NULL_CHECK (cfg, sp [0]->dreg);
11147
11148                                         if (mini_is_gsharedvt_klass (klass)) {
11149                                                 MonoInst *offset_ins;
11150
11151                                                 offset_ins = emit_get_gsharedvt_info (cfg, field, MONO_RGCTX_INFO_FIELD_OFFSET);
11152                                                 dreg = alloc_ireg_mp (cfg);
11153                                                 EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, sp [0]->dreg, offset_ins->dreg);
11154                                                 EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, load, field->type, dreg, 0);
11155                                         } else {
11156                                                 EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, load, field->type, sp [0]->dreg, foffset);
11157                                         }
11158                                         load->flags |= ins_flag;
11159                                         if (sp [0]->opcode != OP_LDADDR)
11160                                                 load->flags |= MONO_INST_FAULT;
11161                                         *sp++ = load;
11162                                 }
11163                         }
11164
11165                         if (is_instance) {
11166                                 ins_flag = 0;
11167                                 ip += 5;
11168                                 break;
11169                         }
11170
11171                         /* STATIC CASE */
11172                         context_used = mini_class_check_context_used (cfg, klass);
11173
11174                         if (ftype->attrs & FIELD_ATTRIBUTE_LITERAL)
11175                                 UNVERIFIED;
11176
11177                         /* The special_static_fields field is init'd in mono_class_vtable, so it needs
11178                          * to be called here.
11179                          */
11180                         if (!context_used && !(cfg->opt & MONO_OPT_SHARED)) {
11181                                 mono_class_vtable (cfg->domain, klass);
11182                                 CHECK_TYPELOAD (klass);
11183                         }
11184                         mono_domain_lock (cfg->domain);
11185                         if (cfg->domain->special_static_fields)
11186                                 addr = g_hash_table_lookup (cfg->domain->special_static_fields, field);
11187                         mono_domain_unlock (cfg->domain);
11188
11189                         is_special_static = mono_class_field_is_special_static (field);
11190
11191                         if (is_special_static && ((gsize)addr & 0x80000000) == 0)
11192                                 thread_ins = mono_get_thread_intrinsic (cfg);
11193                         else
11194                                 thread_ins = NULL;
11195
11196                         /* Generate IR to compute the field address */
11197                         if (is_special_static && ((gsize)addr & 0x80000000) == 0 && thread_ins && !(cfg->opt & MONO_OPT_SHARED) && !context_used) {
11198                                 /*
11199                                  * Fast access to TLS data
11200                                  * Inline version of get_thread_static_data () in
11201                                  * threads.c.
11202                                  */
11203                                 guint32 offset;
11204                                 int idx, static_data_reg, array_reg, dreg;
11205
11206                                 GSHAREDVT_FAILURE (op);
11207
11208                                 MONO_ADD_INS (cfg->cbb, thread_ins);
11209                                 static_data_reg = alloc_ireg (cfg);
11210                                 MONO_EMIT_NEW_LOAD_MEMBASE (cfg, static_data_reg, thread_ins->dreg, MONO_STRUCT_OFFSET (MonoInternalThread, static_data));
11211
11212                                 if (cfg->compile_aot) {
11213                                         int offset_reg, offset2_reg, idx_reg;
11214
11215                                         /* For TLS variables, this will return the TLS offset */
11216                                         EMIT_NEW_SFLDACONST (cfg, ins, field);
11217                                         offset_reg = ins->dreg;
11218                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, offset_reg, offset_reg, 0x7fffffff);
11219                                         idx_reg = alloc_ireg (cfg);
11220                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, idx_reg, offset_reg, 0x3f);
11221                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHL_IMM, idx_reg, idx_reg, sizeof (gpointer) == 8 ? 3 : 2);
11222                                         MONO_EMIT_NEW_BIALU (cfg, OP_PADD, static_data_reg, static_data_reg, idx_reg);
11223                                         array_reg = alloc_ireg (cfg);
11224                                         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, array_reg, static_data_reg, 0);
11225                                         offset2_reg = alloc_ireg (cfg);
11226                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ISHR_UN_IMM, offset2_reg, offset_reg, 6);
11227                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, offset2_reg, offset2_reg, 0x1ffffff);
11228                                         dreg = alloc_ireg (cfg);
11229                                         EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, array_reg, offset2_reg);
11230                                 } else {
11231                                         offset = (gsize)addr & 0x7fffffff;
11232                                         idx = offset & 0x3f;
11233
11234                                         array_reg = alloc_ireg (cfg);
11235                                         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, array_reg, static_data_reg, idx * sizeof (gpointer));
11236                                         dreg = alloc_ireg (cfg);
11237                                         EMIT_NEW_BIALU_IMM (cfg, ins, OP_ADD_IMM, dreg, array_reg, ((offset >> 6) & 0x1ffffff));
11238                                 }
11239                         } else if ((cfg->opt & MONO_OPT_SHARED) ||
11240                                         (cfg->compile_aot && is_special_static) ||
11241                                         (context_used && is_special_static)) {
11242                                 MonoInst *iargs [2];
11243
11244                                 g_assert (field->parent);
11245                                 EMIT_NEW_DOMAINCONST (cfg, iargs [0]);
11246                                 if (context_used) {
11247                                         iargs [1] = emit_get_rgctx_field (cfg, context_used,
11248                                                 field, MONO_RGCTX_INFO_CLASS_FIELD);
11249                                 } else {
11250                                         EMIT_NEW_FIELDCONST (cfg, iargs [1], field);
11251                                 }
11252                                 ins = mono_emit_jit_icall (cfg, mono_class_static_field_address, iargs);
11253                         } else if (context_used) {
11254                                 MonoInst *static_data;
11255
11256                                 /*
11257                                 g_print ("sharing static field access in %s.%s.%s - depth %d offset %d\n",
11258                                         method->klass->name_space, method->klass->name, method->name,
11259                                         depth, field->offset);
11260                                 */
11261
11262                                 if (mono_class_needs_cctor_run (klass, method))
11263                                         emit_class_init (cfg, klass);
11264
11265                                 /*
11266                                  * The pointer we're computing here is
11267                                  *
11268                                  *   super_info.static_data + field->offset
11269                                  */
11270                                 static_data = emit_get_rgctx_klass (cfg, context_used,
11271                                         klass, MONO_RGCTX_INFO_STATIC_DATA);
11272
11273                                 if (mini_is_gsharedvt_klass (klass)) {
11274                                         MonoInst *offset_ins;
11275
11276                                         offset_ins = emit_get_rgctx_field (cfg, context_used, field, MONO_RGCTX_INFO_FIELD_OFFSET);
11277                                         dreg = alloc_ireg_mp (cfg);
11278                                         EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, static_data->dreg, offset_ins->dreg);
11279                                 } else if (field->offset == 0) {
11280                                         ins = static_data;
11281                                 } else {
11282                                         int addr_reg = mono_alloc_preg (cfg);
11283                                         EMIT_NEW_BIALU_IMM (cfg, ins, OP_PADD_IMM, addr_reg, static_data->dreg, field->offset);
11284                                 }
11285                                 } else if ((cfg->opt & MONO_OPT_SHARED) || (cfg->compile_aot && addr)) {
11286                                 MonoInst *iargs [2];
11287
11288                                 g_assert (field->parent);
11289                                 EMIT_NEW_DOMAINCONST (cfg, iargs [0]);
11290                                 EMIT_NEW_FIELDCONST (cfg, iargs [1], field);
11291                                 ins = mono_emit_jit_icall (cfg, mono_class_static_field_address, iargs);
11292                         } else {
11293                                 MonoVTable *vtable = NULL;
11294
11295                                 if (!cfg->compile_aot)
11296                                         vtable = mono_class_vtable (cfg->domain, klass);
11297                                 CHECK_TYPELOAD (klass);
11298
11299                                 if (!addr) {
11300                                         if (mini_field_access_needs_cctor_run (cfg, method, klass, vtable)) {
11301                                                 if (!(g_slist_find (class_inits, klass))) {
11302                                                         emit_class_init (cfg, klass);
11303                                                         if (cfg->verbose_level > 2)
11304                                                                 printf ("class %s.%s needs init call for %s\n", klass->name_space, klass->name, mono_field_get_name (field));
11305                                                         class_inits = g_slist_prepend (class_inits, klass);
11306                                                 }
11307                                         } else {
11308                                                 if (cfg->run_cctors) {
11309                                                         MonoException *ex;
11310                                                         /* This makes so that inline cannot trigger */
11311                                                         /* .cctors: too many apps depend on them */
11312                                                         /* running with a specific order... */
11313                                                         g_assert (vtable);
11314                                                         if (! vtable->initialized)
11315                                                                 INLINE_FAILURE ("class init");
11316                                                         ex = mono_runtime_class_init_full (vtable, FALSE);
11317                                                         if (ex) {
11318                                                                 set_exception_object (cfg, ex);
11319                                                                 goto exception_exit;
11320                                                         }
11321                                                 }
11322                                         }
11323                                         if (cfg->compile_aot)
11324                                                 EMIT_NEW_SFLDACONST (cfg, ins, field);
11325                                         else {
11326                                                 g_assert (vtable);
11327                                                 addr = (char*)mono_vtable_get_static_field_data (vtable) + field->offset;
11328                                                 g_assert (addr);
11329                                                 EMIT_NEW_PCONST (cfg, ins, addr);
11330                                         }
11331                                 } else {
11332                                         MonoInst *iargs [1];
11333                                         EMIT_NEW_ICONST (cfg, iargs [0], GPOINTER_TO_UINT (addr));
11334                                         ins = mono_emit_jit_icall (cfg, mono_get_special_static_data, iargs);
11335                                 }
11336                         }
11337
11338                         /* Generate IR to do the actual load/store operation */
11339
11340                         if ((op == CEE_STFLD || op == CEE_STSFLD) && (ins_flag & MONO_INST_VOLATILE)) {
11341                                 /* Volatile stores have release semantics, see 12.6.7 in Ecma 335 */
11342                                 emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL);
11343                         }
11344
11345                         if (op == CEE_LDSFLDA) {
11346                                 ins->klass = mono_class_from_mono_type (ftype);
11347                                 ins->type = STACK_PTR;
11348                                 *sp++ = ins;
11349                         } else if (op == CEE_STSFLD) {
11350                                 MonoInst *store;
11351
11352                                 EMIT_NEW_STORE_MEMBASE_TYPE (cfg, store, ftype, ins->dreg, 0, store_val->dreg);
11353                                 store->flags |= ins_flag;
11354                         } else {
11355                                 gboolean is_const = FALSE;
11356                                 MonoVTable *vtable = NULL;
11357                                 gpointer addr = NULL;
11358
11359                                 if (!context_used) {
11360                                         vtable = mono_class_vtable (cfg->domain, klass);
11361                                         CHECK_TYPELOAD (klass);
11362                                 }
11363                                 if ((ftype->attrs & FIELD_ATTRIBUTE_INIT_ONLY) && (((addr = mono_aot_readonly_field_override (field)) != NULL) ||
11364                                                 (!context_used && !((cfg->opt & MONO_OPT_SHARED) || cfg->compile_aot) && vtable->initialized))) {
11365                                         int ro_type = ftype->type;
11366                                         if (!addr)
11367                                                 addr = (char*)mono_vtable_get_static_field_data (vtable) + field->offset;
11368                                         if (ro_type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
11369                                                 ro_type = mono_class_enum_basetype (ftype->data.klass)->type;
11370                                         }
11371
11372                                         GSHAREDVT_FAILURE (op);
11373
11374                                         /* printf ("RO-FIELD %s.%s:%s\n", klass->name_space, klass->name, mono_field_get_name (field));*/
11375                                         is_const = TRUE;
11376                                         switch (ro_type) {
11377                                         case MONO_TYPE_BOOLEAN:
11378                                         case MONO_TYPE_U1:
11379                                                 EMIT_NEW_ICONST (cfg, *sp, *((guint8 *)addr));
11380                                                 sp++;
11381                                                 break;
11382                                         case MONO_TYPE_I1:
11383                                                 EMIT_NEW_ICONST (cfg, *sp, *((gint8 *)addr));
11384                                                 sp++;
11385                                                 break;                                          
11386                                         case MONO_TYPE_CHAR:
11387                                         case MONO_TYPE_U2:
11388                                                 EMIT_NEW_ICONST (cfg, *sp, *((guint16 *)addr));
11389                                                 sp++;
11390                                                 break;
11391                                         case MONO_TYPE_I2:
11392                                                 EMIT_NEW_ICONST (cfg, *sp, *((gint16 *)addr));
11393                                                 sp++;
11394                                                 break;
11395                                                 break;
11396                                         case MONO_TYPE_I4:
11397                                                 EMIT_NEW_ICONST (cfg, *sp, *((gint32 *)addr));
11398                                                 sp++;
11399                                                 break;                                          
11400                                         case MONO_TYPE_U4:
11401                                                 EMIT_NEW_ICONST (cfg, *sp, *((guint32 *)addr));
11402                                                 sp++;
11403                                                 break;
11404                                         case MONO_TYPE_I:
11405                                         case MONO_TYPE_U:
11406                                         case MONO_TYPE_PTR:
11407                                         case MONO_TYPE_FNPTR:
11408                                                 EMIT_NEW_PCONST (cfg, *sp, *((gpointer *)addr));
11409                                                 type_to_eval_stack_type ((cfg), field->type, *sp);
11410                                                 sp++;
11411                                                 break;
11412                                         case MONO_TYPE_STRING:
11413                                         case MONO_TYPE_OBJECT:
11414                                         case MONO_TYPE_CLASS:
11415                                         case MONO_TYPE_SZARRAY:
11416                                         case MONO_TYPE_ARRAY:
11417                                                 if (!mono_gc_is_moving ()) {
11418                                                         EMIT_NEW_PCONST (cfg, *sp, *((gpointer *)addr));
11419                                                         type_to_eval_stack_type ((cfg), field->type, *sp);
11420                                                         sp++;
11421                                                 } else {
11422                                                         is_const = FALSE;
11423                                                 }
11424                                                 break;
11425                                         case MONO_TYPE_I8:
11426                                         case MONO_TYPE_U8:
11427                                                 EMIT_NEW_I8CONST (cfg, *sp, *((gint64 *)addr));
11428                                                 sp++;
11429                                                 break;
11430                                         case MONO_TYPE_R4:
11431                                         case MONO_TYPE_R8:
11432                                         case MONO_TYPE_VALUETYPE:
11433                                         default:
11434                                                 is_const = FALSE;
11435                                                 break;
11436                                         }
11437                                 }
11438
11439                                 if (!is_const) {
11440                                         MonoInst *load;
11441
11442                                         CHECK_STACK_OVF (1);
11443
11444                                         EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, load, field->type, ins->dreg, 0);
11445                                         load->flags |= ins_flag;
11446                                         ins_flag = 0;
11447                                         *sp++ = load;
11448                                 }
11449                         }
11450
11451                         if ((op == CEE_LDFLD || op == CEE_LDSFLD) && (ins_flag & MONO_INST_VOLATILE)) {
11452                                 /* Volatile loads have acquire semantics, see 12.6.7 in Ecma 335 */
11453                                 emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_ACQ);
11454                         }
11455
11456                         ins_flag = 0;
11457                         ip += 5;
11458                         break;
11459                 }
11460                 case CEE_STOBJ:
11461                         CHECK_STACK (2);
11462                         sp -= 2;
11463                         CHECK_OPSIZE (5);
11464                         token = read32 (ip + 1);
11465                         klass = mini_get_class (method, token, generic_context);
11466                         CHECK_TYPELOAD (klass);
11467                         if (ins_flag & MONO_INST_VOLATILE) {
11468                                 /* Volatile stores have release semantics, see 12.6.7 in Ecma 335 */
11469                                 emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL);
11470                         }
11471                         /* FIXME: should check item at sp [1] is compatible with the type of the store. */
11472                         EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, sp [0]->dreg, 0, sp [1]->dreg);
11473                         ins->flags |= ins_flag;
11474                         if (cfg->gen_write_barriers && cfg->method->wrapper_type != MONO_WRAPPER_WRITE_BARRIER &&
11475                                         generic_class_is_reference_type (cfg, klass)) {
11476                                 /* insert call to write barrier */
11477                                 emit_write_barrier (cfg, sp [0], sp [1]);
11478                         }
11479                         ins_flag = 0;
11480                         ip += 5;
11481                         inline_costs += 1;
11482                         break;
11483
11484                         /*
11485                          * Array opcodes
11486                          */
11487                 case CEE_NEWARR: {
11488                         MonoInst *len_ins;
11489                         const char *data_ptr;
11490                         int data_size = 0;
11491                         guint32 field_token;
11492
11493                         CHECK_STACK (1);
11494                         --sp;
11495
11496                         CHECK_OPSIZE (5);
11497                         token = read32 (ip + 1);
11498
11499                         klass = mini_get_class (method, token, generic_context);
11500                         CHECK_TYPELOAD (klass);
11501
11502                         context_used = mini_class_check_context_used (cfg, klass);
11503
11504                         if (sp [0]->type == STACK_I8 || (SIZEOF_VOID_P == 8 && sp [0]->type == STACK_PTR)) {
11505                                 MONO_INST_NEW (cfg, ins, OP_LCONV_TO_OVF_U4);
11506                                 ins->sreg1 = sp [0]->dreg;
11507                                 ins->type = STACK_I4;
11508                                 ins->dreg = alloc_ireg (cfg);
11509                                 MONO_ADD_INS (cfg->cbb, ins);
11510                                 *sp = mono_decompose_opcode (cfg, ins);
11511                         }
11512
11513                         if (context_used) {
11514                                 MonoInst *args [3];
11515                                 MonoClass *array_class = mono_array_class_get (klass, 1);
11516                                 MonoMethod *managed_alloc = mono_gc_get_managed_array_allocator (array_class);
11517
11518                                 /* FIXME: Use OP_NEWARR and decompose later to help abcrem */
11519
11520                                 /* vtable */
11521                                 args [0] = emit_get_rgctx_klass (cfg, context_used,
11522                                         array_class, MONO_RGCTX_INFO_VTABLE);
11523                                 /* array len */
11524                                 args [1] = sp [0];
11525
11526                                 if (managed_alloc)
11527                                         ins = mono_emit_method_call (cfg, managed_alloc, args, NULL);
11528                                 else
11529                                         ins = mono_emit_jit_icall (cfg, mono_array_new_specific, args);
11530                         } else {
11531                                 if (cfg->opt & MONO_OPT_SHARED) {
11532                                         /* Decompose now to avoid problems with references to the domainvar */
11533                                         MonoInst *iargs [3];
11534
11535                                         EMIT_NEW_DOMAINCONST (cfg, iargs [0]);
11536                                         EMIT_NEW_CLASSCONST (cfg, iargs [1], klass);
11537                                         iargs [2] = sp [0];
11538
11539                                         ins = mono_emit_jit_icall (cfg, mono_array_new, iargs);
11540                                 } else {
11541                                         /* Decompose later since it is needed by abcrem */
11542                                         MonoClass *array_type = mono_array_class_get (klass, 1);
11543                                         mono_class_vtable (cfg->domain, array_type);
11544                                         CHECK_TYPELOAD (array_type);
11545
11546                                         MONO_INST_NEW (cfg, ins, OP_NEWARR);
11547                                         ins->dreg = alloc_ireg_ref (cfg);
11548                                         ins->sreg1 = sp [0]->dreg;
11549                                         ins->inst_newa_class = klass;
11550                                         ins->type = STACK_OBJ;
11551                                         ins->klass = array_type;
11552                                         MONO_ADD_INS (cfg->cbb, ins);
11553                                         cfg->flags |= MONO_CFG_HAS_ARRAY_ACCESS;
11554                                         cfg->cbb->has_array_access = TRUE;
11555
11556                                         /* Needed so mono_emit_load_get_addr () gets called */
11557                                         mono_get_got_var (cfg);
11558                                 }
11559                         }
11560
11561                         len_ins = sp [0];
11562                         ip += 5;
11563                         *sp++ = ins;
11564                         inline_costs += 1;
11565
11566                         /* 
11567                          * we inline/optimize the initialization sequence if possible.
11568                          * we should also allocate the array as not cleared, since we spend as much time clearing to 0 as initializing
11569                          * for small sizes open code the memcpy
11570                          * ensure the rva field is big enough
11571                          */
11572                         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))) {
11573                                 MonoMethod *memcpy_method = get_memcpy_method ();
11574                                 MonoInst *iargs [3];
11575                                 int add_reg = alloc_ireg_mp (cfg);
11576
11577                                 EMIT_NEW_BIALU_IMM (cfg, iargs [0], OP_PADD_IMM, add_reg, ins->dreg, MONO_STRUCT_OFFSET (MonoArray, vector));
11578                                 if (cfg->compile_aot) {
11579                                         EMIT_NEW_AOTCONST_TOKEN (cfg, iargs [1], MONO_PATCH_INFO_RVA, method->klass->image, GPOINTER_TO_UINT(field_token), STACK_PTR, NULL);
11580                                 } else {
11581                                         EMIT_NEW_PCONST (cfg, iargs [1], (char*)data_ptr);
11582                                 }
11583                                 EMIT_NEW_ICONST (cfg, iargs [2], data_size);
11584                                 mono_emit_method_call (cfg, memcpy_method, iargs, NULL);
11585                                 ip += 11;
11586                         }
11587
11588                         break;
11589                 }
11590                 case CEE_LDLEN:
11591                         CHECK_STACK (1);
11592                         --sp;
11593                         if (sp [0]->type != STACK_OBJ)
11594                                 UNVERIFIED;
11595
11596                         MONO_INST_NEW (cfg, ins, OP_LDLEN);
11597                         ins->dreg = alloc_preg (cfg);
11598                         ins->sreg1 = sp [0]->dreg;
11599                         ins->type = STACK_I4;
11600                         /* This flag will be inherited by the decomposition */
11601                         ins->flags |= MONO_INST_FAULT;
11602                         MONO_ADD_INS (cfg->cbb, ins);
11603                         cfg->flags |= MONO_CFG_HAS_ARRAY_ACCESS;
11604                         cfg->cbb->has_array_access = TRUE;
11605                         ip ++;
11606                         *sp++ = ins;
11607                         break;
11608                 case CEE_LDELEMA:
11609                         CHECK_STACK (2);
11610                         sp -= 2;
11611                         CHECK_OPSIZE (5);
11612                         if (sp [0]->type != STACK_OBJ)
11613                                 UNVERIFIED;
11614
11615                         cfg->flags |= MONO_CFG_HAS_LDELEMA;
11616
11617                         klass = mini_get_class (method, read32 (ip + 1), generic_context);
11618                         CHECK_TYPELOAD (klass);
11619                         /* we need to make sure that this array is exactly the type it needs
11620                          * to be for correctness. the wrappers are lax with their usage
11621                          * so we need to ignore them here
11622                          */
11623                         if (!klass->valuetype && method->wrapper_type == MONO_WRAPPER_NONE && !readonly) {
11624                                 MonoClass *array_class = mono_array_class_get (klass, 1);
11625                                 mini_emit_check_array_type (cfg, sp [0], array_class);
11626                                 CHECK_TYPELOAD (array_class);
11627                         }
11628
11629                         readonly = FALSE;
11630                         ins = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], TRUE);
11631                         *sp++ = ins;
11632                         ip += 5;
11633                         break;
11634                 case CEE_LDELEM:
11635                 case CEE_LDELEM_I1:
11636                 case CEE_LDELEM_U1:
11637                 case CEE_LDELEM_I2:
11638                 case CEE_LDELEM_U2:
11639                 case CEE_LDELEM_I4:
11640                 case CEE_LDELEM_U4:
11641                 case CEE_LDELEM_I8:
11642                 case CEE_LDELEM_I:
11643                 case CEE_LDELEM_R4:
11644                 case CEE_LDELEM_R8:
11645                 case CEE_LDELEM_REF: {
11646                         MonoInst *addr;
11647
11648                         CHECK_STACK (2);
11649                         sp -= 2;
11650
11651                         if (*ip == CEE_LDELEM) {
11652                                 CHECK_OPSIZE (5);
11653                                 token = read32 (ip + 1);
11654                                 klass = mini_get_class (method, token, generic_context);
11655                                 CHECK_TYPELOAD (klass);
11656                                 mono_class_init (klass);
11657                         }
11658                         else
11659                                 klass = array_access_to_klass (*ip);
11660
11661                         if (sp [0]->type != STACK_OBJ)
11662                                 UNVERIFIED;
11663
11664                         cfg->flags |= MONO_CFG_HAS_LDELEMA;
11665
11666                         if (mini_is_gsharedvt_variable_klass (klass)) {
11667                                 // FIXME-VT: OP_ICONST optimization
11668                                 addr = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], TRUE);
11669                                 EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, addr->dreg, 0);
11670                                 ins->opcode = OP_LOADV_MEMBASE;
11671                         } else if (sp [1]->opcode == OP_ICONST) {
11672                                 int array_reg = sp [0]->dreg;
11673                                 int index_reg = sp [1]->dreg;
11674                                 int offset = (mono_class_array_element_size (klass) * sp [1]->inst_c0) + MONO_STRUCT_OFFSET (MonoArray, vector);
11675
11676                                 MONO_EMIT_BOUNDS_CHECK (cfg, array_reg, MonoArray, max_length, index_reg);
11677                                 EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, array_reg, offset);
11678                         } else {
11679                                 addr = mini_emit_ldelema_1_ins (cfg, klass, sp [0], sp [1], TRUE);
11680                                 EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, addr->dreg, 0);
11681                         }
11682                         *sp++ = ins;
11683                         if (*ip == CEE_LDELEM)
11684                                 ip += 5;
11685                         else
11686                                 ++ip;
11687                         break;
11688                 }
11689                 case CEE_STELEM_I:
11690                 case CEE_STELEM_I1:
11691                 case CEE_STELEM_I2:
11692                 case CEE_STELEM_I4:
11693                 case CEE_STELEM_I8:
11694                 case CEE_STELEM_R4:
11695                 case CEE_STELEM_R8:
11696                 case CEE_STELEM_REF:
11697                 case CEE_STELEM: {
11698                         CHECK_STACK (3);
11699                         sp -= 3;
11700
11701                         cfg->flags |= MONO_CFG_HAS_LDELEMA;
11702
11703                         if (*ip == CEE_STELEM) {
11704                                 CHECK_OPSIZE (5);
11705                                 token = read32 (ip + 1);
11706                                 klass = mini_get_class (method, token, generic_context);
11707                                 CHECK_TYPELOAD (klass);
11708                                 mono_class_init (klass);
11709                         }
11710                         else
11711                                 klass = array_access_to_klass (*ip);
11712
11713                         if (sp [0]->type != STACK_OBJ)
11714                                 UNVERIFIED;
11715
11716                         emit_array_store (cfg, klass, sp, TRUE);
11717
11718                         if (*ip == CEE_STELEM)
11719                                 ip += 5;
11720                         else
11721                                 ++ip;
11722                         inline_costs += 1;
11723                         break;
11724                 }
11725                 case CEE_CKFINITE: {
11726                         CHECK_STACK (1);
11727                         --sp;
11728
11729                         if (cfg->llvm_only) {
11730                                 MonoInst *iargs [1];
11731
11732                                 iargs [0] = sp [0];
11733                                 *sp++ = mono_emit_jit_icall (cfg, mono_ckfinite, iargs);
11734                         } else  {
11735                                 MONO_INST_NEW (cfg, ins, OP_CKFINITE);
11736                                 ins->sreg1 = sp [0]->dreg;
11737                                 ins->dreg = alloc_freg (cfg);
11738                                 ins->type = STACK_R8;
11739                                 MONO_ADD_INS (cfg->cbb, ins);
11740
11741                                 *sp++ = mono_decompose_opcode (cfg, ins);
11742                         }
11743
11744                         ++ip;
11745                         break;
11746                 }
11747                 case CEE_REFANYVAL: {
11748                         MonoInst *src_var, *src;
11749
11750                         int klass_reg = alloc_preg (cfg);
11751                         int dreg = alloc_preg (cfg);
11752
11753                         GSHAREDVT_FAILURE (*ip);
11754
11755                         CHECK_STACK (1);
11756                         MONO_INST_NEW (cfg, ins, *ip);
11757                         --sp;
11758                         CHECK_OPSIZE (5);
11759                         klass = mini_get_class (method, read32 (ip + 1), generic_context);
11760                         CHECK_TYPELOAD (klass);
11761
11762                         context_used = mini_class_check_context_used (cfg, klass);
11763
11764                         // FIXME:
11765                         src_var = get_vreg_to_inst (cfg, sp [0]->dreg);
11766                         if (!src_var)
11767                                 src_var = mono_compile_create_var_for_vreg (cfg, &mono_defaults.typed_reference_class->byval_arg, OP_LOCAL, sp [0]->dreg);
11768                         EMIT_NEW_VARLOADA (cfg, src, src_var, src_var->inst_vtype);
11769                         MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, src->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, klass));
11770
11771                         if (context_used) {
11772                                 MonoInst *klass_ins;
11773
11774                                 klass_ins = emit_get_rgctx_klass (cfg, context_used,
11775                                                 klass, MONO_RGCTX_INFO_KLASS);
11776
11777                                 // FIXME:
11778                                 MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, klass_reg, klass_ins->dreg);
11779                                 MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "InvalidCastException");
11780                         } else {
11781                                 mini_emit_class_check (cfg, klass_reg, klass);
11782                         }
11783                         EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, dreg, src->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, value));
11784                         ins->type = STACK_MP;
11785                         ins->klass = klass;
11786                         *sp++ = ins;
11787                         ip += 5;
11788                         break;
11789                 }
11790                 case CEE_MKREFANY: {
11791                         MonoInst *loc, *addr;
11792
11793                         GSHAREDVT_FAILURE (*ip);
11794
11795                         CHECK_STACK (1);
11796                         MONO_INST_NEW (cfg, ins, *ip);
11797                         --sp;
11798                         CHECK_OPSIZE (5);
11799                         klass = mini_get_class (method, read32 (ip + 1), generic_context);
11800                         CHECK_TYPELOAD (klass);
11801
11802                         context_used = mini_class_check_context_used (cfg, klass);
11803
11804                         loc = mono_compile_create_var (cfg, &mono_defaults.typed_reference_class->byval_arg, OP_LOCAL);
11805                         EMIT_NEW_TEMPLOADA (cfg, addr, loc->inst_c0);
11806
11807                         if (context_used) {
11808                                 MonoInst *const_ins;
11809                                 int type_reg = alloc_preg (cfg);
11810
11811                                 const_ins = emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS);
11812                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, klass), const_ins->dreg);
11813                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, type_reg, const_ins->dreg, MONO_STRUCT_OFFSET (MonoClass, byval_arg));
11814                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, type), type_reg);
11815                         } else if (cfg->compile_aot) {
11816                                 int const_reg = alloc_preg (cfg);
11817                                 int type_reg = alloc_preg (cfg);
11818
11819                                 MONO_EMIT_NEW_CLASSCONST (cfg, const_reg, klass);
11820                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, klass), const_reg);
11821                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, type_reg, const_reg, MONO_STRUCT_OFFSET (MonoClass, byval_arg));
11822                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, type), type_reg);
11823                         } else {
11824                                 MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STOREP_MEMBASE_IMM, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, type), &klass->byval_arg);
11825                                 MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STOREP_MEMBASE_IMM, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, klass), klass);
11826                         }
11827                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, value), sp [0]->dreg);
11828
11829                         EMIT_NEW_TEMPLOAD (cfg, ins, loc->inst_c0);
11830                         ins->type = STACK_VTYPE;
11831                         ins->klass = mono_defaults.typed_reference_class;
11832                         *sp++ = ins;
11833                         ip += 5;
11834                         break;
11835                 }
11836                 case CEE_LDTOKEN: {
11837                         gpointer handle;
11838                         MonoClass *handle_class;
11839
11840                         CHECK_STACK_OVF (1);
11841
11842                         CHECK_OPSIZE (5);
11843                         n = read32 (ip + 1);
11844
11845                         if (method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD ||
11846                                         method->wrapper_type == MONO_WRAPPER_SYNCHRONIZED) {
11847                                 handle = mono_method_get_wrapper_data (method, n);
11848                                 handle_class = mono_method_get_wrapper_data (method, n + 1);
11849                                 if (handle_class == mono_defaults.typehandle_class)
11850                                         handle = &((MonoClass*)handle)->byval_arg;
11851                         }
11852                         else {
11853                                 handle = mono_ldtoken_checked (image, n, &handle_class, generic_context, &cfg->error);
11854                                 CHECK_CFG_ERROR;
11855                         }
11856                         if (!handle)
11857                                 LOAD_ERROR;
11858                         mono_class_init (handle_class);
11859                         if (cfg->gshared) {
11860                                 if (mono_metadata_token_table (n) == MONO_TABLE_TYPEDEF ||
11861                                                 mono_metadata_token_table (n) == MONO_TABLE_TYPEREF) {
11862                                         /* This case handles ldtoken
11863                                            of an open type, like for
11864                                            typeof(Gen<>). */
11865                                         context_used = 0;
11866                                 } else if (handle_class == mono_defaults.typehandle_class) {
11867                                         context_used = mini_class_check_context_used (cfg, mono_class_from_mono_type (handle));
11868                                 } else if (handle_class == mono_defaults.fieldhandle_class)
11869                                         context_used = mini_class_check_context_used (cfg, ((MonoClassField*)handle)->parent);
11870                                 else if (handle_class == mono_defaults.methodhandle_class)
11871                                         context_used = mini_method_check_context_used (cfg, handle);
11872                                 else
11873                                         g_assert_not_reached ();
11874                         }
11875
11876                         if ((cfg->opt & MONO_OPT_SHARED) &&
11877                                         method->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD &&
11878                                         method->wrapper_type != MONO_WRAPPER_SYNCHRONIZED) {
11879                                 MonoInst *addr, *vtvar, *iargs [3];
11880                                 int method_context_used;
11881
11882                                 method_context_used = mini_method_check_context_used (cfg, method);
11883
11884                                 vtvar = mono_compile_create_var (cfg, &handle_class->byval_arg, OP_LOCAL); 
11885
11886                                 EMIT_NEW_IMAGECONST (cfg, iargs [0], image);
11887                                 EMIT_NEW_ICONST (cfg, iargs [1], n);
11888                                 if (method_context_used) {
11889                                         iargs [2] = emit_get_rgctx_method (cfg, method_context_used,
11890                                                 method, MONO_RGCTX_INFO_METHOD);
11891                                         ins = mono_emit_jit_icall (cfg, mono_ldtoken_wrapper_generic_shared, iargs);
11892                                 } else {
11893                                         EMIT_NEW_PCONST (cfg, iargs [2], generic_context);
11894                                         ins = mono_emit_jit_icall (cfg, mono_ldtoken_wrapper, iargs);
11895                                 }
11896                                 EMIT_NEW_TEMPLOADA (cfg, addr, vtvar->inst_c0);
11897
11898                                 MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, addr->dreg, 0, ins->dreg);
11899
11900                                 EMIT_NEW_TEMPLOAD (cfg, ins, vtvar->inst_c0);
11901                         } else {
11902                                 if ((ip + 5 < end) && ip_in_bb (cfg, cfg->cbb, ip + 5) && 
11903                                         ((ip [5] == CEE_CALL) || (ip [5] == CEE_CALLVIRT)) && 
11904                                         (cmethod = mini_get_method (cfg, method, read32 (ip + 6), NULL, generic_context)) &&
11905                                         (cmethod->klass == mono_defaults.systemtype_class) &&
11906                                         (strcmp (cmethod->name, "GetTypeFromHandle") == 0)) {
11907                                         MonoClass *tclass = mono_class_from_mono_type (handle);
11908
11909                                         mono_class_init (tclass);
11910                                         if (context_used) {
11911                                                 ins = emit_get_rgctx_klass (cfg, context_used,
11912                                                         tclass, MONO_RGCTX_INFO_REFLECTION_TYPE);
11913                                         } else if (cfg->compile_aot) {
11914                                                 if (method->wrapper_type) {
11915                                                         mono_error_init (&error); //got to do it since there are multiple conditionals below
11916                                                         if (mono_class_get_checked (tclass->image, tclass->type_token, &error) == tclass && !generic_context) {
11917                                                                 /* Special case for static synchronized wrappers */
11918                                                                 EMIT_NEW_TYPE_FROM_HANDLE_CONST (cfg, ins, tclass->image, tclass->type_token, generic_context);
11919                                                         } else {
11920                                                                 mono_error_cleanup (&error); /* FIXME don't swallow the error */
11921                                                                 /* FIXME: n is not a normal token */
11922                                                                 DISABLE_AOT (cfg);
11923                                                                 EMIT_NEW_PCONST (cfg, ins, NULL);
11924                                                         }
11925                                                 } else {
11926                                                         EMIT_NEW_TYPE_FROM_HANDLE_CONST (cfg, ins, image, n, generic_context);
11927                                                 }
11928                                         } else {
11929                                                 EMIT_NEW_PCONST (cfg, ins, mono_type_get_object (cfg->domain, handle));
11930                                         }
11931                                         ins->type = STACK_OBJ;
11932                                         ins->klass = cmethod->klass;
11933                                         ip += 5;
11934                                 } else {
11935                                         MonoInst *addr, *vtvar;
11936
11937                                         vtvar = mono_compile_create_var (cfg, &handle_class->byval_arg, OP_LOCAL);
11938
11939                                         if (context_used) {
11940                                                 if (handle_class == mono_defaults.typehandle_class) {
11941                                                         ins = emit_get_rgctx_klass (cfg, context_used,
11942                                                                         mono_class_from_mono_type (handle),
11943                                                                         MONO_RGCTX_INFO_TYPE);
11944                                                 } else if (handle_class == mono_defaults.methodhandle_class) {
11945                                                         ins = emit_get_rgctx_method (cfg, context_used,
11946                                                                         handle, MONO_RGCTX_INFO_METHOD);
11947                                                 } else if (handle_class == mono_defaults.fieldhandle_class) {
11948                                                         ins = emit_get_rgctx_field (cfg, context_used,
11949                                                                         handle, MONO_RGCTX_INFO_CLASS_FIELD);
11950                                                 } else {
11951                                                         g_assert_not_reached ();
11952                                                 }
11953                                         } else if (cfg->compile_aot) {
11954                                                 EMIT_NEW_LDTOKENCONST (cfg, ins, image, n, generic_context);
11955                                         } else {
11956                                                 EMIT_NEW_PCONST (cfg, ins, handle);
11957                                         }
11958                                         EMIT_NEW_TEMPLOADA (cfg, addr, vtvar->inst_c0);
11959                                         MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, addr->dreg, 0, ins->dreg);
11960                                         EMIT_NEW_TEMPLOAD (cfg, ins, vtvar->inst_c0);
11961                                 }
11962                         }
11963
11964                         *sp++ = ins;
11965                         ip += 5;
11966                         break;
11967                 }
11968                 case CEE_THROW:
11969                         CHECK_STACK (1);
11970                         MONO_INST_NEW (cfg, ins, OP_THROW);
11971                         --sp;
11972                         ins->sreg1 = sp [0]->dreg;
11973                         ip++;
11974                         cfg->cbb->out_of_line = TRUE;
11975                         MONO_ADD_INS (cfg->cbb, ins);
11976                         MONO_INST_NEW (cfg, ins, OP_NOT_REACHED);
11977                         MONO_ADD_INS (cfg->cbb, ins);
11978                         sp = stack_start;
11979                         
11980                         link_bblock (cfg, cfg->cbb, end_bblock);
11981                         start_new_bblock = 1;
11982                         /* This can complicate code generation for llvm since the return value might not be defined */
11983                         if (COMPILE_LLVM (cfg))
11984                                 INLINE_FAILURE ("throw");
11985                         break;
11986                 case CEE_ENDFINALLY:
11987                         /* mono_save_seq_point_info () depends on this */
11988                         if (sp != stack_start)
11989                                 emit_seq_point (cfg, method, ip, FALSE, FALSE);
11990                         MONO_INST_NEW (cfg, ins, OP_ENDFINALLY);
11991                         MONO_ADD_INS (cfg->cbb, ins);
11992                         ip++;
11993                         start_new_bblock = 1;
11994
11995                         /*
11996                          * Control will leave the method so empty the stack, otherwise
11997                          * the next basic block will start with a nonempty stack.
11998                          */
11999                         while (sp != stack_start) {
12000                                 sp--;
12001                         }
12002                         break;
12003                 case CEE_LEAVE:
12004                 case CEE_LEAVE_S: {
12005                         GList *handlers;
12006
12007                         if (*ip == CEE_LEAVE) {
12008                                 CHECK_OPSIZE (5);
12009                                 target = ip + 5 + (gint32)read32(ip + 1);
12010                         } else {
12011                                 CHECK_OPSIZE (2);
12012                                 target = ip + 2 + (signed char)(ip [1]);
12013                         }
12014
12015                         /* empty the stack */
12016                         while (sp != stack_start) {
12017                                 sp--;
12018                         }
12019
12020                         /* 
12021                          * If this leave statement is in a catch block, check for a
12022                          * pending exception, and rethrow it if necessary.
12023                          * We avoid doing this in runtime invoke wrappers, since those are called
12024                          * by native code which excepts the wrapper to catch all exceptions.
12025                          */
12026                         for (i = 0; i < header->num_clauses; ++i) {
12027                                 MonoExceptionClause *clause = &header->clauses [i];
12028
12029                                 /* 
12030                                  * Use <= in the final comparison to handle clauses with multiple
12031                                  * leave statements, like in bug #78024.
12032                                  * The ordering of the exception clauses guarantees that we find the
12033                                  * innermost clause.
12034                                  */
12035                                 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) {
12036                                         MonoInst *exc_ins;
12037                                         MonoBasicBlock *dont_throw;
12038
12039                                         /*
12040                                           MonoInst *load;
12041
12042                                           NEW_TEMPLOAD (cfg, load, mono_find_exvar_for_offset (cfg, clause->handler_offset)->inst_c0);
12043                                         */
12044
12045                                         exc_ins = mono_emit_jit_icall (cfg, mono_thread_get_undeniable_exception, NULL);
12046
12047                                         NEW_BBLOCK (cfg, dont_throw);
12048
12049                                         /*
12050                                          * Currently, we always rethrow the abort exception, despite the 
12051                                          * fact that this is not correct. See thread6.cs for an example. 
12052                                          * But propagating the abort exception is more important than 
12053                                          * getting the sematics right.
12054                                          */
12055                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, exc_ins->dreg, 0);
12056                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, dont_throw);
12057                                         MONO_EMIT_NEW_UNALU (cfg, OP_THROW, -1, exc_ins->dreg);
12058
12059                                         MONO_START_BB (cfg, dont_throw);
12060                                 }
12061                         }
12062
12063 #ifdef ENABLE_LLVM
12064                         cfg->cbb->try_end = (intptr_t)(ip - header->code);
12065 #endif
12066
12067                         if ((handlers = mono_find_final_block (cfg, ip, target, MONO_EXCEPTION_CLAUSE_FINALLY))) {
12068                                 GList *tmp;
12069                                 MonoExceptionClause *clause;
12070
12071                                 for (tmp = handlers; tmp; tmp = tmp->next) {
12072                                         clause = tmp->data;
12073                                         tblock = cfg->cil_offset_to_bb [clause->handler_offset];
12074                                         g_assert (tblock);
12075                                         link_bblock (cfg, cfg->cbb, tblock);
12076                                         MONO_INST_NEW (cfg, ins, OP_CALL_HANDLER);
12077                                         ins->inst_target_bb = tblock;
12078                                         ins->inst_eh_block = clause;
12079                                         MONO_ADD_INS (cfg->cbb, ins);
12080                                         cfg->cbb->has_call_handler = 1;
12081                                         if (COMPILE_LLVM (cfg)) {
12082                                                 MonoBasicBlock *target_bb;
12083
12084                                                 /* 
12085                                                  * Link the finally bblock with the target, since it will
12086                                                  * conceptually branch there.
12087                                                  * FIXME: Have to link the bblock containing the endfinally.
12088                                                  */
12089                                                 GET_BBLOCK (cfg, target_bb, target);
12090                                                 link_bblock (cfg, tblock, target_bb);
12091                                         }
12092                                 }
12093                                 g_list_free (handlers);
12094                         } 
12095
12096                         MONO_INST_NEW (cfg, ins, OP_BR);
12097                         MONO_ADD_INS (cfg->cbb, ins);
12098                         GET_BBLOCK (cfg, tblock, target);
12099                         link_bblock (cfg, cfg->cbb, tblock);
12100                         ins->inst_target_bb = tblock;
12101
12102                         start_new_bblock = 1;
12103
12104                         if (*ip == CEE_LEAVE)
12105                                 ip += 5;
12106                         else
12107                                 ip += 2;
12108
12109                         break;
12110                 }
12111
12112                         /*
12113                          * Mono specific opcodes
12114                          */
12115                 case MONO_CUSTOM_PREFIX: {
12116
12117                         g_assert (method->wrapper_type != MONO_WRAPPER_NONE);
12118
12119                         CHECK_OPSIZE (2);
12120                         switch (ip [1]) {
12121                         case CEE_MONO_ICALL: {
12122                                 gpointer func;
12123                                 MonoJitICallInfo *info;
12124
12125                                 token = read32 (ip + 2);
12126                                 func = mono_method_get_wrapper_data (method, token);
12127                                 info = mono_find_jit_icall_by_addr (func);
12128                                 if (!info)
12129                                         g_error ("Could not find icall address in wrapper %s", mono_method_full_name (method, 1));
12130                                 g_assert (info);
12131
12132                                 CHECK_STACK (info->sig->param_count);
12133                                 sp -= info->sig->param_count;
12134
12135                                 ins = mono_emit_jit_icall (cfg, info->func, sp);
12136                                 if (!MONO_TYPE_IS_VOID (info->sig->ret))
12137                                         *sp++ = ins;
12138
12139                                 ip += 6;
12140                                 inline_costs += 10 * num_calls++;
12141
12142                                 break;
12143                         }
12144                         case CEE_MONO_LDPTR_CARD_TABLE: {
12145                                 int shift_bits;
12146                                 gpointer card_mask;
12147                                 CHECK_STACK_OVF (1);
12148
12149                                 if (cfg->compile_aot)
12150                                         EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_GC_CARD_TABLE_ADDR, NULL);
12151                                 else
12152                                         EMIT_NEW_PCONST (cfg, ins, mono_gc_get_card_table (&shift_bits, &card_mask));
12153
12154                                 *sp++ = ins;
12155                                 ip += 2;
12156                                 inline_costs += 10 * num_calls++;
12157                                 break;
12158                         }
12159                         case CEE_MONO_LDPTR_NURSERY_START: {
12160                                 int shift_bits;
12161                                 size_t size;
12162                                 CHECK_STACK_OVF (1);
12163
12164                                 if (cfg->compile_aot)
12165                                         EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_GC_NURSERY_START, NULL);
12166                                 else
12167                                         EMIT_NEW_PCONST (cfg, ins, mono_gc_get_nursery (&shift_bits, &size));
12168
12169                                 *sp++ = ins;
12170                                 ip += 2;
12171                                 inline_costs += 10 * num_calls++;
12172                                 break;
12173                         }
12174                         case CEE_MONO_LDPTR_INT_REQ_FLAG: {
12175                                 CHECK_STACK_OVF (1);
12176
12177                                 if (cfg->compile_aot)
12178                                         EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG, NULL);
12179                                 else
12180                                         EMIT_NEW_PCONST (cfg, ins, mono_thread_interruption_request_flag ());
12181
12182                                 *sp++ = ins;
12183                                 ip += 2;
12184                                 inline_costs += 10 * num_calls++;
12185                                 break;
12186                         }
12187                         case CEE_MONO_LDPTR: {
12188                                 gpointer ptr;
12189
12190                                 CHECK_STACK_OVF (1);
12191                                 CHECK_OPSIZE (6);
12192                                 token = read32 (ip + 2);
12193
12194                                 ptr = mono_method_get_wrapper_data (method, token);
12195                                 EMIT_NEW_PCONST (cfg, ins, ptr);
12196                                 *sp++ = ins;
12197                                 ip += 6;
12198                                 inline_costs += 10 * num_calls++;
12199                                 /* Can't embed random pointers into AOT code */
12200                                 DISABLE_AOT (cfg);
12201                                 break;
12202                         }
12203                         case CEE_MONO_JIT_ICALL_ADDR: {
12204                                 MonoJitICallInfo *callinfo;
12205                                 gpointer ptr;
12206
12207                                 CHECK_STACK_OVF (1);
12208                                 CHECK_OPSIZE (6);
12209                                 token = read32 (ip + 2);
12210
12211                                 ptr = mono_method_get_wrapper_data (method, token);
12212                                 callinfo = mono_find_jit_icall_by_addr (ptr);
12213                                 g_assert (callinfo);
12214                                 EMIT_NEW_JIT_ICALL_ADDRCONST (cfg, ins, (char*)callinfo->name);
12215                                 *sp++ = ins;
12216                                 ip += 6;
12217                                 inline_costs += 10 * num_calls++;
12218                                 break;
12219                         }
12220                         case CEE_MONO_ICALL_ADDR: {
12221                                 MonoMethod *cmethod;
12222                                 gpointer ptr;
12223
12224                                 CHECK_STACK_OVF (1);
12225                                 CHECK_OPSIZE (6);
12226                                 token = read32 (ip + 2);
12227
12228                                 cmethod = mono_method_get_wrapper_data (method, token);
12229
12230                                 if (cfg->compile_aot) {
12231                                         EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_ICALL_ADDR, cmethod);
12232                                 } else {
12233                                         ptr = mono_lookup_internal_call (cmethod);
12234                                         g_assert (ptr);
12235                                         EMIT_NEW_PCONST (cfg, ins, ptr);
12236                                 }
12237                                 *sp++ = ins;
12238                                 ip += 6;
12239                                 break;
12240                         }
12241                         case CEE_MONO_VTADDR: {
12242                                 MonoInst *src_var, *src;
12243
12244                                 CHECK_STACK (1);
12245                                 --sp;
12246
12247                                 // FIXME:
12248                                 src_var = get_vreg_to_inst (cfg, sp [0]->dreg);
12249                                 EMIT_NEW_VARLOADA ((cfg), (src), src_var, src_var->inst_vtype);
12250                                 *sp++ = src;
12251                                 ip += 2;
12252                                 break;
12253                         }
12254                         case CEE_MONO_NEWOBJ: {
12255                                 MonoInst *iargs [2];
12256
12257                                 CHECK_STACK_OVF (1);
12258                                 CHECK_OPSIZE (6);
12259                                 token = read32 (ip + 2);
12260                                 klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
12261                                 mono_class_init (klass);
12262                                 NEW_DOMAINCONST (cfg, iargs [0]);
12263                                 MONO_ADD_INS (cfg->cbb, iargs [0]);
12264                                 NEW_CLASSCONST (cfg, iargs [1], klass);
12265                                 MONO_ADD_INS (cfg->cbb, iargs [1]);
12266                                 *sp++ = mono_emit_jit_icall (cfg, mono_object_new, iargs);
12267                                 ip += 6;
12268                                 inline_costs += 10 * num_calls++;
12269                                 break;
12270                         }
12271                         case CEE_MONO_OBJADDR:
12272                                 CHECK_STACK (1);
12273                                 --sp;
12274                                 MONO_INST_NEW (cfg, ins, OP_MOVE);
12275                                 ins->dreg = alloc_ireg_mp (cfg);
12276                                 ins->sreg1 = sp [0]->dreg;
12277                                 ins->type = STACK_MP;
12278                                 MONO_ADD_INS (cfg->cbb, ins);
12279                                 *sp++ = ins;
12280                                 ip += 2;
12281                                 break;
12282                         case CEE_MONO_LDNATIVEOBJ:
12283                                 /*
12284                                  * Similar to LDOBJ, but instead load the unmanaged 
12285                                  * representation of the vtype to the stack.
12286                                  */
12287                                 CHECK_STACK (1);
12288                                 CHECK_OPSIZE (6);
12289                                 --sp;
12290                                 token = read32 (ip + 2);
12291                                 klass = mono_method_get_wrapper_data (method, token);
12292                                 g_assert (klass->valuetype);
12293                                 mono_class_init (klass);
12294
12295                                 {
12296                                         MonoInst *src, *dest, *temp;
12297
12298                                         src = sp [0];
12299                                         temp = mono_compile_create_var (cfg, &klass->byval_arg, OP_LOCAL);
12300                                         temp->backend.is_pinvoke = 1;
12301                                         EMIT_NEW_TEMPLOADA (cfg, dest, temp->inst_c0);
12302                                         mini_emit_stobj (cfg, dest, src, klass, TRUE);
12303
12304                                         EMIT_NEW_TEMPLOAD (cfg, dest, temp->inst_c0);
12305                                         dest->type = STACK_VTYPE;
12306                                         dest->klass = klass;
12307
12308                                         *sp ++ = dest;
12309                                         ip += 6;
12310                                 }
12311                                 break;
12312                         case CEE_MONO_RETOBJ: {
12313                                 /*
12314                                  * Same as RET, but return the native representation of a vtype
12315                                  * to the caller.
12316                                  */
12317                                 g_assert (cfg->ret);
12318                                 g_assert (mono_method_signature (method)->pinvoke); 
12319                                 CHECK_STACK (1);
12320                                 --sp;
12321                                 
12322                                 CHECK_OPSIZE (6);
12323                                 token = read32 (ip + 2);    
12324                                 klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
12325
12326                                 if (!cfg->vret_addr) {
12327                                         g_assert (cfg->ret_var_is_local);
12328
12329                                         EMIT_NEW_VARLOADA (cfg, ins, cfg->ret, cfg->ret->inst_vtype);
12330                                 } else {
12331                                         EMIT_NEW_RETLOADA (cfg, ins);
12332                                 }
12333                                 mini_emit_stobj (cfg, ins, sp [0], klass, TRUE);
12334                                 
12335                                 if (sp != stack_start)
12336                                         UNVERIFIED;
12337                                 
12338                                 MONO_INST_NEW (cfg, ins, OP_BR);
12339                                 ins->inst_target_bb = end_bblock;
12340                                 MONO_ADD_INS (cfg->cbb, ins);
12341                                 link_bblock (cfg, cfg->cbb, end_bblock);
12342                                 start_new_bblock = 1;
12343                                 ip += 6;
12344                                 break;
12345                         }
12346                         case CEE_MONO_CISINST:
12347                         case CEE_MONO_CCASTCLASS: {
12348                                 int token;
12349                                 CHECK_STACK (1);
12350                                 --sp;
12351                                 CHECK_OPSIZE (6);
12352                                 token = read32 (ip + 2);
12353                                 klass = (MonoClass *)mono_method_get_wrapper_data (method, token);
12354                                 if (ip [1] == CEE_MONO_CISINST)
12355                                         ins = handle_cisinst (cfg, klass, sp [0]);
12356                                 else
12357                                         ins = handle_ccastclass (cfg, klass, sp [0]);
12358                                 *sp++ = ins;
12359                                 ip += 6;
12360                                 break;
12361                         }
12362                         case CEE_MONO_SAVE_LMF:
12363                         case CEE_MONO_RESTORE_LMF:
12364                                 ip += 2;
12365                                 break;
12366                         case CEE_MONO_CLASSCONST:
12367                                 CHECK_STACK_OVF (1);
12368                                 CHECK_OPSIZE (6);
12369                                 token = read32 (ip + 2);
12370                                 EMIT_NEW_CLASSCONST (cfg, ins, mono_method_get_wrapper_data (method, token));
12371                                 *sp++ = ins;
12372                                 ip += 6;
12373                                 inline_costs += 10 * num_calls++;
12374                                 break;
12375                         case CEE_MONO_NOT_TAKEN:
12376                                 cfg->cbb->out_of_line = TRUE;
12377                                 ip += 2;
12378                                 break;
12379                         case CEE_MONO_TLS: {
12380                                 int key;
12381
12382                                 CHECK_STACK_OVF (1);
12383                                 CHECK_OPSIZE (6);
12384                                 key = (gint32)read32 (ip + 2);
12385                                 g_assert (key < TLS_KEY_NUM);
12386
12387                                 ins = mono_create_tls_get (cfg, key);
12388                                 if (!ins) {
12389                                         if (cfg->compile_aot) {
12390                                                 DISABLE_AOT (cfg);
12391                                                 MONO_INST_NEW (cfg, ins, OP_TLS_GET);
12392                                                 ins->dreg = alloc_preg (cfg);
12393                                                 ins->type = STACK_PTR;
12394                                         } else {
12395                                                 g_assert_not_reached ();
12396                                         }
12397                                 }
12398                                 ins->type = STACK_PTR;
12399                                 MONO_ADD_INS (cfg->cbb, ins);
12400                                 *sp++ = ins;
12401                                 ip += 6;
12402                                 break;
12403                         }
12404                         case CEE_MONO_DYN_CALL: {
12405                                 MonoCallInst *call;
12406
12407                                 /* It would be easier to call a trampoline, but that would put an
12408                                  * extra frame on the stack, confusing exception handling. So
12409                                  * implement it inline using an opcode for now.
12410                                  */
12411
12412                                 if (!cfg->dyn_call_var) {
12413                                         cfg->dyn_call_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
12414                                         /* prevent it from being register allocated */
12415                                         cfg->dyn_call_var->flags |= MONO_INST_VOLATILE;
12416                                 }
12417
12418                                 /* Has to use a call inst since it local regalloc expects it */
12419                                 MONO_INST_NEW_CALL (cfg, call, OP_DYN_CALL);
12420                                 ins = (MonoInst*)call;
12421                                 sp -= 2;
12422                                 ins->sreg1 = sp [0]->dreg;
12423                                 ins->sreg2 = sp [1]->dreg;
12424                                 MONO_ADD_INS (cfg->cbb, ins);
12425
12426                                 cfg->param_area = MAX (cfg->param_area, cfg->backend->dyn_call_param_area);
12427
12428                                 ip += 2;
12429                                 inline_costs += 10 * num_calls++;
12430
12431                                 break;
12432                         }
12433                         case CEE_MONO_MEMORY_BARRIER: {
12434                                 CHECK_OPSIZE (6);
12435                                 emit_memory_barrier (cfg, (int)read32 (ip + 2));
12436                                 ip += 6;
12437                                 break;
12438                         }
12439                         case CEE_MONO_JIT_ATTACH: {
12440                                 MonoInst *args [16], *domain_ins;
12441                                 MonoInst *ad_ins, *jit_tls_ins;
12442                                 MonoBasicBlock *next_bb = NULL, *call_bb = NULL;
12443
12444                                 cfg->orig_domain_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
12445
12446                                 EMIT_NEW_PCONST (cfg, ins, NULL);
12447                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->orig_domain_var->dreg, ins->dreg);
12448
12449                                 ad_ins = mono_get_domain_intrinsic (cfg);
12450                                 jit_tls_ins = mono_get_jit_tls_intrinsic (cfg);
12451
12452                                 if (cfg->backend->have_tls_get && ad_ins && jit_tls_ins) {
12453                                         NEW_BBLOCK (cfg, next_bb);
12454                                         NEW_BBLOCK (cfg, call_bb);
12455
12456                                         if (cfg->compile_aot) {
12457                                                 /* AOT code is only used in the root domain */
12458                                                 EMIT_NEW_PCONST (cfg, domain_ins, NULL);
12459                                         } else {
12460                                                 EMIT_NEW_PCONST (cfg, domain_ins, cfg->domain);
12461                                         }
12462                                         MONO_ADD_INS (cfg->cbb, ad_ins);
12463                                         MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, ad_ins->dreg, domain_ins->dreg);
12464                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, call_bb);
12465
12466                                         MONO_ADD_INS (cfg->cbb, jit_tls_ins);
12467                                         MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, jit_tls_ins->dreg, 0);
12468                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, call_bb);
12469
12470                                         MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, next_bb);
12471                                         MONO_START_BB (cfg, call_bb);
12472                                 }
12473
12474                                 if (cfg->compile_aot) {
12475                                         /* AOT code is only used in the root domain */
12476                                         EMIT_NEW_PCONST (cfg, args [0], NULL);
12477                                 } else {
12478                                         EMIT_NEW_PCONST (cfg, args [0], cfg->domain);
12479                                 }
12480                                 ins = mono_emit_jit_icall (cfg, mono_jit_thread_attach, args);
12481                                 MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->orig_domain_var->dreg, ins->dreg);
12482
12483                                 if (next_bb)
12484                                         MONO_START_BB (cfg, next_bb);
12485                                 ip += 2;
12486                                 break;
12487                         }
12488                         case CEE_MONO_JIT_DETACH: {
12489                                 MonoInst *args [16];
12490
12491                                 /* Restore the original domain */
12492                                 dreg = alloc_ireg (cfg);
12493                                 EMIT_NEW_UNALU (cfg, args [0], OP_MOVE, dreg, cfg->orig_domain_var->dreg);
12494                                 mono_emit_jit_icall (cfg, mono_jit_set_domain, args);
12495                                 ip += 2;
12496                                 break;
12497                         }
12498                         default:
12499                                 g_error ("opcode 0x%02x 0x%02x not handled", MONO_CUSTOM_PREFIX, ip [1]);
12500                                 break;
12501                         }
12502                         break;
12503                 }
12504
12505                 case CEE_PREFIX1: {
12506                         CHECK_OPSIZE (2);
12507                         switch (ip [1]) {
12508                         case CEE_ARGLIST: {
12509                                 /* somewhat similar to LDTOKEN */
12510                                 MonoInst *addr, *vtvar;
12511                                 CHECK_STACK_OVF (1);
12512                                 vtvar = mono_compile_create_var (cfg, &mono_defaults.argumenthandle_class->byval_arg, OP_LOCAL); 
12513
12514                                 EMIT_NEW_TEMPLOADA (cfg, addr, vtvar->inst_c0);
12515                                 EMIT_NEW_UNALU (cfg, ins, OP_ARGLIST, -1, addr->dreg);
12516
12517                                 EMIT_NEW_TEMPLOAD (cfg, ins, vtvar->inst_c0);
12518                                 ins->type = STACK_VTYPE;
12519                                 ins->klass = mono_defaults.argumenthandle_class;
12520                                 *sp++ = ins;
12521                                 ip += 2;
12522                                 break;
12523                         }
12524                         case CEE_CEQ:
12525                         case CEE_CGT:
12526                         case CEE_CGT_UN:
12527                         case CEE_CLT:
12528                         case CEE_CLT_UN: {
12529                                 MonoInst *cmp, *arg1, *arg2;
12530
12531                                 CHECK_STACK (2);
12532                                 sp -= 2;
12533                                 arg1 = sp [0];
12534                                 arg2 = sp [1];
12535
12536                                 /*
12537                                  * The following transforms:
12538                                  *    CEE_CEQ    into OP_CEQ
12539                                  *    CEE_CGT    into OP_CGT
12540                                  *    CEE_CGT_UN into OP_CGT_UN
12541                                  *    CEE_CLT    into OP_CLT
12542                                  *    CEE_CLT_UN into OP_CLT_UN
12543                                  */
12544                                 MONO_INST_NEW (cfg, cmp, (OP_CEQ - CEE_CEQ) + ip [1]);
12545
12546                                 MONO_INST_NEW (cfg, ins, cmp->opcode);
12547                                 cmp->sreg1 = arg1->dreg;
12548                                 cmp->sreg2 = arg2->dreg;
12549                                 type_from_op (cfg, cmp, arg1, arg2);
12550                                 CHECK_TYPE (cmp);
12551                                 add_widen_op (cfg, cmp, &arg1, &arg2);
12552                                 if ((arg1->type == STACK_I8) || ((SIZEOF_VOID_P == 8) && ((arg1->type == STACK_PTR) || (arg1->type == STACK_OBJ) || (arg1->type == STACK_MP))))
12553                                         cmp->opcode = OP_LCOMPARE;
12554                                 else if (arg1->type == STACK_R4)
12555                                         cmp->opcode = OP_RCOMPARE;
12556                                 else if (arg1->type == STACK_R8)
12557                                         cmp->opcode = OP_FCOMPARE;
12558                                 else
12559                                         cmp->opcode = OP_ICOMPARE;
12560                                 MONO_ADD_INS (cfg->cbb, cmp);
12561                                 ins->type = STACK_I4;
12562                                 ins->dreg = alloc_dreg (cfg, ins->type);
12563                                 type_from_op (cfg, ins, arg1, arg2);
12564
12565                                 if (cmp->opcode == OP_FCOMPARE || cmp->opcode == OP_RCOMPARE) {
12566                                         /*
12567                                          * The backends expect the fceq opcodes to do the
12568                                          * comparison too.
12569                                          */
12570                                         ins->sreg1 = cmp->sreg1;
12571                                         ins->sreg2 = cmp->sreg2;
12572                                         NULLIFY_INS (cmp);
12573                                 }
12574                                 MONO_ADD_INS (cfg->cbb, ins);
12575                                 *sp++ = ins;
12576                                 ip += 2;
12577                                 break;
12578                         }
12579                         case CEE_LDFTN: {
12580                                 MonoInst *argconst;
12581                                 MonoMethod *cil_method;
12582
12583                                 CHECK_STACK_OVF (1);
12584                                 CHECK_OPSIZE (6);
12585                                 n = read32 (ip + 2);
12586                                 cmethod = mini_get_method (cfg, method, n, NULL, generic_context);
12587                                 if (!cmethod || mono_loader_get_last_error ())
12588                                         LOAD_ERROR;
12589                                 mono_class_init (cmethod->klass);
12590
12591                                 mono_save_token_info (cfg, image, n, cmethod);
12592
12593                                 context_used = mini_method_check_context_used (cfg, cmethod);
12594
12595                                 cil_method = cmethod;
12596                                 if (!dont_verify && !cfg->skip_visibility && !mono_method_can_access_method (method, cmethod))
12597                                         METHOD_ACCESS_FAILURE (method, cil_method);
12598
12599                                 if (mono_security_core_clr_enabled ())
12600                                         ensure_method_is_allowed_to_call_method (cfg, method, cmethod);
12601
12602                                 /* 
12603                                  * Optimize the common case of ldftn+delegate creation
12604                                  */
12605                                 if ((sp > stack_start) && (ip + 6 + 5 < end) && ip_in_bb (cfg, cfg->cbb, ip + 6) && (ip [6] == CEE_NEWOBJ)) {
12606                                         MonoMethod *ctor_method = mini_get_method (cfg, method, read32 (ip + 7), NULL, generic_context);
12607                                         if (ctor_method && (ctor_method->klass->parent == mono_defaults.multicastdelegate_class)) {
12608                                                 MonoInst *target_ins, *handle_ins;
12609                                                 MonoMethod *invoke;
12610                                                 int invoke_context_used;
12611
12612                                                 invoke = mono_get_delegate_invoke (ctor_method->klass);
12613                                                 if (!invoke || !mono_method_signature (invoke))
12614                                                         LOAD_ERROR;
12615
12616                                                 invoke_context_used = mini_method_check_context_used (cfg, invoke);
12617
12618                                                 target_ins = sp [-1];
12619
12620                                                 if (mono_security_core_clr_enabled ())
12621                                                         ensure_method_is_allowed_to_call_method (cfg, method, ctor_method);
12622
12623                                                 if (!(cmethod->flags & METHOD_ATTRIBUTE_STATIC)) {
12624                                                         /*LAME IMPL: We must not add a null check for virtual invoke delegates.*/
12625                                                         if (mono_method_signature (invoke)->param_count == mono_method_signature (cmethod)->param_count) {
12626                                                                 MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, target_ins->dreg, 0);
12627                                                                 MONO_EMIT_NEW_COND_EXC (cfg, EQ, "ArgumentException");
12628                                                         }
12629                                                 }
12630
12631                                                 /* FIXME: SGEN support */
12632                                                 if (invoke_context_used == 0) {
12633                                                         ip += 6;
12634                                                         if (cfg->verbose_level > 3)
12635                                                                 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));
12636                                                         if ((handle_ins = handle_delegate_ctor (cfg, ctor_method->klass, target_ins, cmethod, context_used, FALSE))) {
12637                                                                 sp --;
12638                                                                 *sp = handle_ins;
12639                                                                 CHECK_CFG_EXCEPTION;
12640                                                                 ip += 5;
12641                                                                 sp ++;
12642                                                                 break;
12643                                                         }
12644                                                         ip -= 6;
12645                                                 }
12646                                         }
12647                                 }
12648
12649                                 argconst = emit_get_rgctx_method (cfg, context_used, cmethod, MONO_RGCTX_INFO_METHOD);
12650                                 ins = mono_emit_jit_icall (cfg, mono_ldftn, &argconst);
12651                                 *sp++ = ins;
12652                                 
12653                                 ip += 6;
12654                                 inline_costs += 10 * num_calls++;
12655                                 break;
12656                         }
12657                         case CEE_LDVIRTFTN: {
12658                                 MonoInst *args [2];
12659
12660                                 CHECK_STACK (1);
12661                                 CHECK_OPSIZE (6);
12662                                 n = read32 (ip + 2);
12663                                 cmethod = mini_get_method (cfg, method, n, NULL, generic_context);
12664                                 if (!cmethod || mono_loader_get_last_error ())
12665                                         LOAD_ERROR;
12666                                 mono_class_init (cmethod->klass);
12667  
12668                                 context_used = mini_method_check_context_used (cfg, cmethod);
12669
12670                                 if (mono_security_core_clr_enabled ())
12671                                         ensure_method_is_allowed_to_call_method (cfg, method, cmethod);
12672
12673                                 /*
12674                                  * Optimize the common case of ldvirtftn+delegate creation
12675                                  */
12676                                 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)) {
12677                                         MonoMethod *ctor_method = mini_get_method (cfg, method, read32 (ip + 7), NULL, generic_context);
12678                                         if (ctor_method && (ctor_method->klass->parent == mono_defaults.multicastdelegate_class)) {
12679                                                 MonoInst *target_ins, *handle_ins;
12680                                                 MonoMethod *invoke;
12681                                                 int invoke_context_used;
12682                                                 gboolean is_virtual = cmethod->flags & METHOD_ATTRIBUTE_VIRTUAL;
12683
12684                                                 invoke = mono_get_delegate_invoke (ctor_method->klass);
12685                                                 if (!invoke || !mono_method_signature (invoke))
12686                                                         LOAD_ERROR;
12687
12688                                                 invoke_context_used = mini_method_check_context_used (cfg, invoke);
12689
12690                                                 target_ins = sp [-1];
12691
12692                                                 if (mono_security_core_clr_enabled ())
12693                                                         ensure_method_is_allowed_to_call_method (cfg, method, ctor_method);
12694
12695                                                 /* FIXME: SGEN support */
12696                                                 if (invoke_context_used == 0 || cfg->llvm_only) {
12697                                                         ip += 6;
12698                                                         if (cfg->verbose_level > 3)
12699                                                                 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));
12700                                                         if ((handle_ins = handle_delegate_ctor (cfg, ctor_method->klass, target_ins, cmethod, context_used, is_virtual))) {
12701                                                                 sp -= 2;
12702                                                                 *sp = handle_ins;
12703                                                                 CHECK_CFG_EXCEPTION;
12704                                                                 ip += 5;
12705                                                                 sp ++;
12706                                                                 break;
12707                                                         }
12708                                                         ip -= 6;
12709                                                 }
12710                                         }
12711                                 }
12712
12713                                 --sp;
12714                                 args [0] = *sp;
12715
12716                                 args [1] = emit_get_rgctx_method (cfg, context_used,
12717                                                                                                   cmethod, MONO_RGCTX_INFO_METHOD);
12718
12719                                 if (context_used)
12720                                         *sp++ = mono_emit_jit_icall (cfg, mono_ldvirtfn_gshared, args);
12721                                 else
12722                                         *sp++ = mono_emit_jit_icall (cfg, mono_ldvirtfn, args);
12723
12724                                 ip += 6;
12725                                 inline_costs += 10 * num_calls++;
12726                                 break;
12727                         }
12728                         case CEE_LDARG:
12729                                 CHECK_STACK_OVF (1);
12730                                 CHECK_OPSIZE (4);
12731                                 n = read16 (ip + 2);
12732                                 CHECK_ARG (n);
12733                                 EMIT_NEW_ARGLOAD (cfg, ins, n);
12734                                 *sp++ = ins;
12735                                 ip += 4;
12736                                 break;
12737                         case CEE_LDARGA:
12738                                 CHECK_STACK_OVF (1);
12739                                 CHECK_OPSIZE (4);
12740                                 n = read16 (ip + 2);
12741                                 CHECK_ARG (n);
12742                                 NEW_ARGLOADA (cfg, ins, n);
12743                                 MONO_ADD_INS (cfg->cbb, ins);
12744                                 *sp++ = ins;
12745                                 ip += 4;
12746                                 break;
12747                         case CEE_STARG:
12748                                 CHECK_STACK (1);
12749                                 --sp;
12750                                 CHECK_OPSIZE (4);
12751                                 n = read16 (ip + 2);
12752                                 CHECK_ARG (n);
12753                                 if (!dont_verify_stloc && target_type_is_incompatible (cfg, param_types [n], *sp))
12754                                         UNVERIFIED;
12755                                 EMIT_NEW_ARGSTORE (cfg, ins, n, *sp);
12756                                 ip += 4;
12757                                 break;
12758                         case CEE_LDLOC:
12759                                 CHECK_STACK_OVF (1);
12760                                 CHECK_OPSIZE (4);
12761                                 n = read16 (ip + 2);
12762                                 CHECK_LOCAL (n);
12763                                 EMIT_NEW_LOCLOAD (cfg, ins, n);
12764                                 *sp++ = ins;
12765                                 ip += 4;
12766                                 break;
12767                         case CEE_LDLOCA: {
12768                                 unsigned char *tmp_ip;
12769                                 CHECK_STACK_OVF (1);
12770                                 CHECK_OPSIZE (4);
12771                                 n = read16 (ip + 2);
12772                                 CHECK_LOCAL (n);
12773
12774                                 if ((tmp_ip = emit_optimized_ldloca_ir (cfg, ip, end, 2))) {
12775                                         ip = tmp_ip;
12776                                         inline_costs += 1;
12777                                         break;
12778                                 }                       
12779                                 
12780                                 EMIT_NEW_LOCLOADA (cfg, ins, n);
12781                                 *sp++ = ins;
12782                                 ip += 4;
12783                                 break;
12784                         }
12785                         case CEE_STLOC:
12786                                 CHECK_STACK (1);
12787                                 --sp;
12788                                 CHECK_OPSIZE (4);
12789                                 n = read16 (ip + 2);
12790                                 CHECK_LOCAL (n);
12791                                 if (!dont_verify_stloc && target_type_is_incompatible (cfg, header->locals [n], *sp))
12792                                         UNVERIFIED;
12793                                 emit_stloc_ir (cfg, sp, header, n);
12794                                 ip += 4;
12795                                 inline_costs += 1;
12796                                 break;
12797                         case CEE_LOCALLOC:
12798                                 CHECK_STACK (1);
12799                                 --sp;
12800                                 if (sp != stack_start) 
12801                                         UNVERIFIED;
12802                                 if (cfg->method != method) 
12803                                         /* 
12804                                          * Inlining this into a loop in a parent could lead to 
12805                                          * stack overflows which is different behavior than the
12806                                          * non-inlined case, thus disable inlining in this case.
12807                                          */
12808                                         INLINE_FAILURE("localloc");
12809
12810                                 MONO_INST_NEW (cfg, ins, OP_LOCALLOC);
12811                                 ins->dreg = alloc_preg (cfg);
12812                                 ins->sreg1 = sp [0]->dreg;
12813                                 ins->type = STACK_PTR;
12814                                 MONO_ADD_INS (cfg->cbb, ins);
12815
12816                                 cfg->flags |= MONO_CFG_HAS_ALLOCA;
12817                                 if (init_locals)
12818                                         ins->flags |= MONO_INST_INIT;
12819
12820                                 *sp++ = ins;
12821                                 ip += 2;
12822                                 break;
12823                         case CEE_ENDFILTER: {
12824                                 MonoExceptionClause *clause, *nearest;
12825                                 int cc;
12826
12827                                 CHECK_STACK (1);
12828                                 --sp;
12829                                 if ((sp != stack_start) || (sp [0]->type != STACK_I4)) 
12830                                         UNVERIFIED;
12831                                 MONO_INST_NEW (cfg, ins, OP_ENDFILTER);
12832                                 ins->sreg1 = (*sp)->dreg;
12833                                 MONO_ADD_INS (cfg->cbb, ins);
12834                                 start_new_bblock = 1;
12835                                 ip += 2;
12836
12837                                 nearest = NULL;
12838                                 for (cc = 0; cc < header->num_clauses; ++cc) {
12839                                         clause = &header->clauses [cc];
12840                                         if ((clause->flags & MONO_EXCEPTION_CLAUSE_FILTER) &&
12841                                                 ((ip - header->code) > clause->data.filter_offset && (ip - header->code) <= clause->handler_offset) &&
12842                                             (!nearest || (clause->data.filter_offset < nearest->data.filter_offset)))
12843                                                 nearest = clause;
12844                                 }
12845                                 g_assert (nearest);
12846                                 if ((ip - header->code) != nearest->handler_offset)
12847                                         UNVERIFIED;
12848
12849                                 break;
12850                         }
12851                         case CEE_UNALIGNED_:
12852                                 ins_flag |= MONO_INST_UNALIGNED;
12853                                 /* FIXME: record alignment? we can assume 1 for now */
12854                                 CHECK_OPSIZE (3);
12855                                 ip += 3;
12856                                 break;
12857                         case CEE_VOLATILE_:
12858                                 ins_flag |= MONO_INST_VOLATILE;
12859                                 ip += 2;
12860                                 break;
12861                         case CEE_TAIL_:
12862                                 ins_flag   |= MONO_INST_TAILCALL;
12863                                 cfg->flags |= MONO_CFG_HAS_TAIL;
12864                                 /* Can't inline tail calls at this time */
12865                                 inline_costs += 100000;
12866                                 ip += 2;
12867                                 break;
12868                         case CEE_INITOBJ:
12869                                 CHECK_STACK (1);
12870                                 --sp;
12871                                 CHECK_OPSIZE (6);
12872                                 token = read32 (ip + 2);
12873                                 klass = mini_get_class (method, token, generic_context);
12874                                 CHECK_TYPELOAD (klass);
12875                                 if (generic_class_is_reference_type (cfg, klass))
12876                                         MONO_EMIT_NEW_STORE_MEMBASE_IMM (cfg, OP_STORE_MEMBASE_IMM, sp [0]->dreg, 0, 0);
12877                                 else
12878                                         mini_emit_initobj (cfg, *sp, NULL, klass);
12879                                 ip += 6;
12880                                 inline_costs += 1;
12881                                 break;
12882                         case CEE_CONSTRAINED_:
12883                                 CHECK_OPSIZE (6);
12884                                 token = read32 (ip + 2);
12885                                 constrained_class = mini_get_class (method, token, generic_context);
12886                                 CHECK_TYPELOAD (constrained_class);
12887                                 ip += 6;
12888                                 break;
12889                         case CEE_CPBLK:
12890                         case CEE_INITBLK: {
12891                                 MonoInst *iargs [3];
12892                                 CHECK_STACK (3);
12893                                 sp -= 3;
12894
12895                                 /* Skip optimized paths for volatile operations. */
12896                                 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)) {
12897                                         mini_emit_memcpy (cfg, sp [0]->dreg, 0, sp [1]->dreg, 0, sp [2]->inst_c0, 0);
12898                                 } 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)) {
12899                                         /* emit_memset only works when val == 0 */
12900                                         mini_emit_memset (cfg, sp [0]->dreg, 0, sp [2]->inst_c0, sp [1]->inst_c0, 0);
12901                                 } else {
12902                                         MonoInst *call;
12903                                         iargs [0] = sp [0];
12904                                         iargs [1] = sp [1];
12905                                         iargs [2] = sp [2];
12906                                         if (ip [1] == CEE_CPBLK) {
12907                                                 /*
12908                                                  * FIXME: It's unclear whether we should be emitting both the acquire
12909                                                  * and release barriers for cpblk. It is technically both a load and
12910                                                  * store operation, so it seems like that's the sensible thing to do.
12911                                                  *
12912                                                  * FIXME: We emit full barriers on both sides of the operation for
12913                                                  * simplicity. We should have a separate atomic memcpy method instead.
12914                                                  */
12915                                                 MonoMethod *memcpy_method = get_memcpy_method ();
12916
12917                                                 if (ins_flag & MONO_INST_VOLATILE)
12918                                                         emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_SEQ);
12919
12920                                                 call = mono_emit_method_call (cfg, memcpy_method, iargs, NULL);
12921                                                 call->flags |= ins_flag;
12922
12923                                                 if (ins_flag & MONO_INST_VOLATILE)
12924                                                         emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_SEQ);
12925                                         } else {
12926                                                 MonoMethod *memset_method = get_memset_method ();
12927                                                 if (ins_flag & MONO_INST_VOLATILE) {
12928                                                         /* Volatile stores have release semantics, see 12.6.7 in Ecma 335 */
12929                                                         emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL);
12930                                                 }
12931                                                 call = mono_emit_method_call (cfg, memset_method, iargs, NULL);
12932                                                 call->flags |= ins_flag;
12933                                         }
12934                                 }
12935                                 ip += 2;
12936                                 ins_flag = 0;
12937                                 inline_costs += 1;
12938                                 break;
12939                         }
12940                         case CEE_NO_:
12941                                 CHECK_OPSIZE (3);
12942                                 if (ip [2] & 0x1)
12943                                         ins_flag |= MONO_INST_NOTYPECHECK;
12944                                 if (ip [2] & 0x2)
12945                                         ins_flag |= MONO_INST_NORANGECHECK;
12946                                 /* we ignore the no-nullcheck for now since we
12947                                  * really do it explicitly only when doing callvirt->call
12948                                  */
12949                                 ip += 3;
12950                                 break;
12951                         case CEE_RETHROW: {
12952                                 MonoInst *load;
12953                                 int handler_offset = -1;
12954
12955                                 for (i = 0; i < header->num_clauses; ++i) {
12956                                         MonoExceptionClause *clause = &header->clauses [i];
12957                                         if (MONO_OFFSET_IN_HANDLER (clause, ip - header->code) && !(clause->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
12958                                                 handler_offset = clause->handler_offset;
12959                                                 break;
12960                                         }
12961                                 }
12962
12963                                 cfg->cbb->flags |= BB_EXCEPTION_UNSAFE;
12964
12965                                 if (handler_offset == -1)
12966                                         UNVERIFIED;
12967
12968                                 EMIT_NEW_TEMPLOAD (cfg, load, mono_find_exvar_for_offset (cfg, handler_offset)->inst_c0);
12969                                 MONO_INST_NEW (cfg, ins, OP_RETHROW);
12970                                 ins->sreg1 = load->dreg;
12971                                 MONO_ADD_INS (cfg->cbb, ins);
12972
12973                                 MONO_INST_NEW (cfg, ins, OP_NOT_REACHED);
12974                                 MONO_ADD_INS (cfg->cbb, ins);
12975
12976                                 sp = stack_start;
12977                                 link_bblock (cfg, cfg->cbb, end_bblock);
12978                                 start_new_bblock = 1;
12979                                 ip += 2;
12980                                 break;
12981                         }
12982                         case CEE_SIZEOF: {
12983                                 guint32 val;
12984                                 int ialign;
12985
12986                                 CHECK_STACK_OVF (1);
12987                                 CHECK_OPSIZE (6);
12988                                 token = read32 (ip + 2);
12989                                 if (mono_metadata_token_table (token) == MONO_TABLE_TYPESPEC && !image_is_dynamic (method->klass->image) && !generic_context) {
12990                                         MonoType *type = mono_type_create_from_typespec_checked (image, token, &cfg->error);
12991                                         CHECK_CFG_ERROR;
12992
12993                                         val = mono_type_size (type, &ialign);
12994                                 } else {
12995                                         MonoClass *klass = mini_get_class (method, token, generic_context);
12996                                         CHECK_TYPELOAD (klass);
12997
12998                                         val = mono_type_size (&klass->byval_arg, &ialign);
12999
13000                                         if (mini_is_gsharedvt_klass (klass))
13001                                                 GSHAREDVT_FAILURE (*ip);
13002                                 }
13003                                 EMIT_NEW_ICONST (cfg, ins, val);
13004                                 *sp++= ins;
13005                                 ip += 6;
13006                                 break;
13007                         }
13008                         case CEE_REFANYTYPE: {
13009                                 MonoInst *src_var, *src;
13010
13011                                 GSHAREDVT_FAILURE (*ip);
13012
13013                                 CHECK_STACK (1);
13014                                 --sp;
13015
13016                                 // FIXME:
13017                                 src_var = get_vreg_to_inst (cfg, sp [0]->dreg);
13018                                 if (!src_var)
13019                                         src_var = mono_compile_create_var_for_vreg (cfg, &mono_defaults.typed_reference_class->byval_arg, OP_LOCAL, sp [0]->dreg);
13020                                 EMIT_NEW_VARLOADA (cfg, src, src_var, src_var->inst_vtype);
13021                                 EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, &mono_defaults.typehandle_class->byval_arg, src->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, type));
13022                                 *sp++ = ins;
13023                                 ip += 2;
13024                                 break;
13025                         }
13026                         case CEE_READONLY_:
13027                                 readonly = TRUE;
13028                                 ip += 2;
13029                                 break;
13030
13031                         case CEE_UNUSED56:
13032                         case CEE_UNUSED57:
13033                         case CEE_UNUSED70:
13034                         case CEE_UNUSED:
13035                         case CEE_UNUSED99:
13036                                 UNVERIFIED;
13037                                 
13038                         default:
13039                                 g_warning ("opcode 0xfe 0x%02x not handled", ip [1]);
13040                                 UNVERIFIED;
13041                         }
13042                         break;
13043                 }
13044                 case CEE_UNUSED58:
13045                 case CEE_UNUSED1:
13046                         UNVERIFIED;
13047
13048                 default:
13049                         g_warning ("opcode 0x%02x not handled", *ip);
13050                         UNVERIFIED;
13051                 }
13052         }
13053         if (start_new_bblock != 1)
13054                 UNVERIFIED;
13055
13056         cfg->cbb->cil_length = ip - cfg->cbb->cil_code;
13057         if (cfg->cbb->next_bb) {
13058                 /* This could already be set because of inlining, #693905 */
13059                 MonoBasicBlock *bb = cfg->cbb;
13060
13061                 while (bb->next_bb)
13062                         bb = bb->next_bb;
13063                 bb->next_bb = end_bblock;
13064         } else {
13065                 cfg->cbb->next_bb = end_bblock;
13066         }
13067
13068         if (cfg->method == method && cfg->domainvar) {
13069                 MonoInst *store;
13070                 MonoInst *get_domain;
13071
13072                 cfg->cbb = init_localsbb;
13073
13074                 if ((get_domain = mono_get_domain_intrinsic (cfg))) {
13075                         MONO_ADD_INS (cfg->cbb, get_domain);
13076                 } else {
13077                         get_domain = mono_emit_jit_icall (cfg, mono_domain_get, NULL);
13078                 }
13079                 NEW_TEMPSTORE (cfg, store, cfg->domainvar->inst_c0, get_domain);
13080                 MONO_ADD_INS (cfg->cbb, store);
13081         }
13082
13083 #if defined(TARGET_POWERPC) || defined(TARGET_X86)
13084         if (cfg->compile_aot)
13085                 /* FIXME: The plt slots require a GOT var even if the method doesn't use it */
13086                 mono_get_got_var (cfg);
13087 #endif
13088
13089         if (cfg->method == method && cfg->got_var)
13090                 mono_emit_load_got_addr (cfg);
13091
13092         if (init_localsbb) {
13093                 cfg->cbb = init_localsbb;
13094                 cfg->ip = NULL;
13095                 for (i = 0; i < header->num_locals; ++i) {
13096                         emit_init_local (cfg, i, header->locals [i], init_locals);
13097                 }
13098         }
13099
13100         if (cfg->init_ref_vars && cfg->method == method) {
13101                 /* Emit initialization for ref vars */
13102                 // FIXME: Avoid duplication initialization for IL locals.
13103                 for (i = 0; i < cfg->num_varinfo; ++i) {
13104                         MonoInst *ins = cfg->varinfo [i];
13105
13106                         if (ins->opcode == OP_LOCAL && ins->type == STACK_OBJ)
13107                                 MONO_EMIT_NEW_PCONST (cfg, ins->dreg, NULL);
13108                 }
13109         }
13110
13111         if (cfg->lmf_var && cfg->method == method && !cfg->llvm_only) {
13112                 cfg->cbb = init_localsbb;
13113                 emit_push_lmf (cfg);
13114         }
13115
13116         cfg->cbb = init_localsbb;
13117         emit_instrumentation_call (cfg, mono_profiler_method_enter);
13118
13119         if (seq_points) {
13120                 MonoBasicBlock *bb;
13121
13122                 /*
13123                  * Make seq points at backward branch targets interruptable.
13124                  */
13125                 for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
13126                         if (bb->code && bb->in_count > 1 && bb->code->opcode == OP_SEQ_POINT)
13127                                 bb->code->flags |= MONO_INST_SINGLE_STEP_LOC;
13128         }
13129
13130         /* Add a sequence point for method entry/exit events */
13131         if (seq_points && cfg->gen_sdb_seq_points) {
13132                 NEW_SEQ_POINT (cfg, ins, METHOD_ENTRY_IL_OFFSET, FALSE);
13133                 MONO_ADD_INS (init_localsbb, ins);
13134                 NEW_SEQ_POINT (cfg, ins, METHOD_EXIT_IL_OFFSET, FALSE);
13135                 MONO_ADD_INS (cfg->bb_exit, ins);
13136         }
13137
13138         /*
13139          * Add seq points for IL offsets which have line number info, but wasn't generated a seq point during JITting because
13140          * the code they refer to was dead (#11880).
13141          */
13142         if (sym_seq_points) {
13143                 for (i = 0; i < header->code_size; ++i) {
13144                         if (mono_bitset_test_fast (seq_point_locs, i) && !mono_bitset_test_fast (seq_point_set_locs, i)) {
13145                                 MonoInst *ins;
13146
13147                                 NEW_SEQ_POINT (cfg, ins, i, FALSE);
13148                                 mono_add_seq_point (cfg, NULL, ins, SEQ_POINT_NATIVE_OFFSET_DEAD_CODE);
13149                         }
13150                 }
13151         }
13152
13153         cfg->ip = NULL;
13154
13155         if (cfg->method == method) {
13156                 MonoBasicBlock *bb;
13157                 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
13158                         bb->region = mono_find_block_region (cfg, bb->real_offset);
13159                         if (cfg->spvars)
13160                                 mono_create_spvar_for_region (cfg, bb->region);
13161                         if (cfg->verbose_level > 2)
13162                                 printf ("REGION BB%d IL_%04x ID_%08X\n", bb->block_num, bb->real_offset, bb->region);
13163                 }
13164         }
13165
13166         if (inline_costs < 0) {
13167                 char *mname;
13168
13169                 /* Method is too large */
13170                 mname = mono_method_full_name (method, TRUE);
13171                 mono_cfg_set_exception (cfg, MONO_EXCEPTION_INVALID_PROGRAM);
13172                 cfg->exception_message = g_strdup_printf ("Method %s is too complex.", mname);
13173                 g_free (mname);
13174         }
13175
13176         if ((cfg->verbose_level > 2) && (cfg->method == method)) 
13177                 mono_print_code (cfg, "AFTER METHOD-TO-IR");
13178
13179         goto cleanup;
13180
13181 mono_error_exit:
13182         g_assert (!mono_error_ok (&cfg->error));
13183         goto cleanup;
13184  
13185  exception_exit:
13186         g_assert (cfg->exception_type != MONO_EXCEPTION_NONE);
13187         goto cleanup;
13188
13189  unverified:
13190         set_exception_type_from_invalid_il (cfg, method, ip);
13191         goto cleanup;
13192
13193  cleanup:
13194         g_slist_free (class_inits);
13195         mono_basic_block_free (original_bb);
13196         cfg->dont_inline = g_list_remove (cfg->dont_inline, method);
13197         cfg->headers_to_free = g_slist_prepend_mempool (cfg->mempool, cfg->headers_to_free, header);
13198         if (cfg->exception_type)
13199                 return -1;
13200         else
13201                 return inline_costs;
13202 }
13203
13204 static int
13205 store_membase_reg_to_store_membase_imm (int opcode)
13206 {
13207         switch (opcode) {
13208         case OP_STORE_MEMBASE_REG:
13209                 return OP_STORE_MEMBASE_IMM;
13210         case OP_STOREI1_MEMBASE_REG:
13211                 return OP_STOREI1_MEMBASE_IMM;
13212         case OP_STOREI2_MEMBASE_REG:
13213                 return OP_STOREI2_MEMBASE_IMM;
13214         case OP_STOREI4_MEMBASE_REG:
13215                 return OP_STOREI4_MEMBASE_IMM;
13216         case OP_STOREI8_MEMBASE_REG:
13217                 return OP_STOREI8_MEMBASE_IMM;
13218         default:
13219                 g_assert_not_reached ();
13220         }
13221
13222         return -1;
13223 }               
13224
13225 int
13226 mono_op_to_op_imm (int opcode)
13227 {
13228         switch (opcode) {
13229         case OP_IADD:
13230                 return OP_IADD_IMM;
13231         case OP_ISUB:
13232                 return OP_ISUB_IMM;
13233         case OP_IDIV:
13234                 return OP_IDIV_IMM;
13235         case OP_IDIV_UN:
13236                 return OP_IDIV_UN_IMM;
13237         case OP_IREM:
13238                 return OP_IREM_IMM;
13239         case OP_IREM_UN:
13240                 return OP_IREM_UN_IMM;
13241         case OP_IMUL:
13242                 return OP_IMUL_IMM;
13243         case OP_IAND:
13244                 return OP_IAND_IMM;
13245         case OP_IOR:
13246                 return OP_IOR_IMM;
13247         case OP_IXOR:
13248                 return OP_IXOR_IMM;
13249         case OP_ISHL:
13250                 return OP_ISHL_IMM;
13251         case OP_ISHR:
13252                 return OP_ISHR_IMM;
13253         case OP_ISHR_UN:
13254                 return OP_ISHR_UN_IMM;
13255
13256         case OP_LADD:
13257                 return OP_LADD_IMM;
13258         case OP_LSUB:
13259                 return OP_LSUB_IMM;
13260         case OP_LAND:
13261                 return OP_LAND_IMM;
13262         case OP_LOR:
13263                 return OP_LOR_IMM;
13264         case OP_LXOR:
13265                 return OP_LXOR_IMM;
13266         case OP_LSHL:
13267                 return OP_LSHL_IMM;
13268         case OP_LSHR:
13269                 return OP_LSHR_IMM;
13270         case OP_LSHR_UN:
13271                 return OP_LSHR_UN_IMM;
13272 #if SIZEOF_REGISTER == 8
13273         case OP_LREM:
13274                 return OP_LREM_IMM;
13275 #endif
13276
13277         case OP_COMPARE:
13278                 return OP_COMPARE_IMM;
13279         case OP_ICOMPARE:
13280                 return OP_ICOMPARE_IMM;
13281         case OP_LCOMPARE:
13282                 return OP_LCOMPARE_IMM;
13283
13284         case OP_STORE_MEMBASE_REG:
13285                 return OP_STORE_MEMBASE_IMM;
13286         case OP_STOREI1_MEMBASE_REG:
13287                 return OP_STOREI1_MEMBASE_IMM;
13288         case OP_STOREI2_MEMBASE_REG:
13289                 return OP_STOREI2_MEMBASE_IMM;
13290         case OP_STOREI4_MEMBASE_REG:
13291                 return OP_STOREI4_MEMBASE_IMM;
13292
13293 #if defined(TARGET_X86) || defined (TARGET_AMD64)
13294         case OP_X86_PUSH:
13295                 return OP_X86_PUSH_IMM;
13296         case OP_X86_COMPARE_MEMBASE_REG:
13297                 return OP_X86_COMPARE_MEMBASE_IMM;
13298 #endif
13299 #if defined(TARGET_AMD64)
13300         case OP_AMD64_ICOMPARE_MEMBASE_REG:
13301                 return OP_AMD64_ICOMPARE_MEMBASE_IMM;
13302 #endif
13303         case OP_VOIDCALL_REG:
13304                 return OP_VOIDCALL;
13305         case OP_CALL_REG:
13306                 return OP_CALL;
13307         case OP_LCALL_REG:
13308                 return OP_LCALL;
13309         case OP_FCALL_REG:
13310                 return OP_FCALL;
13311         case OP_LOCALLOC:
13312                 return OP_LOCALLOC_IMM;
13313         }
13314
13315         return -1;
13316 }
13317
13318 static int
13319 ldind_to_load_membase (int opcode)
13320 {
13321         switch (opcode) {
13322         case CEE_LDIND_I1:
13323                 return OP_LOADI1_MEMBASE;
13324         case CEE_LDIND_U1:
13325                 return OP_LOADU1_MEMBASE;
13326         case CEE_LDIND_I2:
13327                 return OP_LOADI2_MEMBASE;
13328         case CEE_LDIND_U2:
13329                 return OP_LOADU2_MEMBASE;
13330         case CEE_LDIND_I4:
13331                 return OP_LOADI4_MEMBASE;
13332         case CEE_LDIND_U4:
13333                 return OP_LOADU4_MEMBASE;
13334         case CEE_LDIND_I:
13335                 return OP_LOAD_MEMBASE;
13336         case CEE_LDIND_REF:
13337                 return OP_LOAD_MEMBASE;
13338         case CEE_LDIND_I8:
13339                 return OP_LOADI8_MEMBASE;
13340         case CEE_LDIND_R4:
13341                 return OP_LOADR4_MEMBASE;
13342         case CEE_LDIND_R8:
13343                 return OP_LOADR8_MEMBASE;
13344         default:
13345                 g_assert_not_reached ();
13346         }
13347
13348         return -1;
13349 }
13350
13351 static int
13352 stind_to_store_membase (int opcode)
13353 {
13354         switch (opcode) {
13355         case CEE_STIND_I1:
13356                 return OP_STOREI1_MEMBASE_REG;
13357         case CEE_STIND_I2:
13358                 return OP_STOREI2_MEMBASE_REG;
13359         case CEE_STIND_I4:
13360                 return OP_STOREI4_MEMBASE_REG;
13361         case CEE_STIND_I:
13362         case CEE_STIND_REF:
13363                 return OP_STORE_MEMBASE_REG;
13364         case CEE_STIND_I8:
13365                 return OP_STOREI8_MEMBASE_REG;
13366         case CEE_STIND_R4:
13367                 return OP_STORER4_MEMBASE_REG;
13368         case CEE_STIND_R8:
13369                 return OP_STORER8_MEMBASE_REG;
13370         default:
13371                 g_assert_not_reached ();
13372         }
13373
13374         return -1;
13375 }
13376
13377 int
13378 mono_load_membase_to_load_mem (int opcode)
13379 {
13380         // FIXME: Add a MONO_ARCH_HAVE_LOAD_MEM macro
13381 #if defined(TARGET_X86) || defined(TARGET_AMD64)
13382         switch (opcode) {
13383         case OP_LOAD_MEMBASE:
13384                 return OP_LOAD_MEM;
13385         case OP_LOADU1_MEMBASE:
13386                 return OP_LOADU1_MEM;
13387         case OP_LOADU2_MEMBASE:
13388                 return OP_LOADU2_MEM;
13389         case OP_LOADI4_MEMBASE:
13390                 return OP_LOADI4_MEM;
13391         case OP_LOADU4_MEMBASE:
13392                 return OP_LOADU4_MEM;
13393 #if SIZEOF_REGISTER == 8
13394         case OP_LOADI8_MEMBASE:
13395                 return OP_LOADI8_MEM;
13396 #endif
13397         }
13398 #endif
13399
13400         return -1;
13401 }
13402
13403 static inline int
13404 op_to_op_dest_membase (int store_opcode, int opcode)
13405 {
13406 #if defined(TARGET_X86)
13407         if (!((store_opcode == OP_STORE_MEMBASE_REG) || (store_opcode == OP_STOREI4_MEMBASE_REG)))
13408                 return -1;
13409
13410         switch (opcode) {
13411         case OP_IADD:
13412                 return OP_X86_ADD_MEMBASE_REG;
13413         case OP_ISUB:
13414                 return OP_X86_SUB_MEMBASE_REG;
13415         case OP_IAND:
13416                 return OP_X86_AND_MEMBASE_REG;
13417         case OP_IOR:
13418                 return OP_X86_OR_MEMBASE_REG;
13419         case OP_IXOR:
13420                 return OP_X86_XOR_MEMBASE_REG;
13421         case OP_ADD_IMM:
13422         case OP_IADD_IMM:
13423                 return OP_X86_ADD_MEMBASE_IMM;
13424         case OP_SUB_IMM:
13425         case OP_ISUB_IMM:
13426                 return OP_X86_SUB_MEMBASE_IMM;
13427         case OP_AND_IMM:
13428         case OP_IAND_IMM:
13429                 return OP_X86_AND_MEMBASE_IMM;
13430         case OP_OR_IMM:
13431         case OP_IOR_IMM:
13432                 return OP_X86_OR_MEMBASE_IMM;
13433         case OP_XOR_IMM:
13434         case OP_IXOR_IMM:
13435                 return OP_X86_XOR_MEMBASE_IMM;
13436         case OP_MOVE:
13437                 return OP_NOP;
13438         }
13439 #endif
13440
13441 #if defined(TARGET_AMD64)
13442         if (!((store_opcode == OP_STORE_MEMBASE_REG) || (store_opcode == OP_STOREI4_MEMBASE_REG) || (store_opcode == OP_STOREI8_MEMBASE_REG)))
13443                 return -1;
13444
13445         switch (opcode) {
13446         case OP_IADD:
13447                 return OP_X86_ADD_MEMBASE_REG;
13448         case OP_ISUB:
13449                 return OP_X86_SUB_MEMBASE_REG;
13450         case OP_IAND:
13451                 return OP_X86_AND_MEMBASE_REG;
13452         case OP_IOR:
13453                 return OP_X86_OR_MEMBASE_REG;
13454         case OP_IXOR:
13455                 return OP_X86_XOR_MEMBASE_REG;
13456         case OP_IADD_IMM:
13457                 return OP_X86_ADD_MEMBASE_IMM;
13458         case OP_ISUB_IMM:
13459                 return OP_X86_SUB_MEMBASE_IMM;
13460         case OP_IAND_IMM:
13461                 return OP_X86_AND_MEMBASE_IMM;
13462         case OP_IOR_IMM:
13463                 return OP_X86_OR_MEMBASE_IMM;
13464         case OP_IXOR_IMM:
13465                 return OP_X86_XOR_MEMBASE_IMM;
13466         case OP_LADD:
13467                 return OP_AMD64_ADD_MEMBASE_REG;
13468         case OP_LSUB:
13469                 return OP_AMD64_SUB_MEMBASE_REG;
13470         case OP_LAND:
13471                 return OP_AMD64_AND_MEMBASE_REG;
13472         case OP_LOR:
13473                 return OP_AMD64_OR_MEMBASE_REG;
13474         case OP_LXOR:
13475                 return OP_AMD64_XOR_MEMBASE_REG;
13476         case OP_ADD_IMM:
13477         case OP_LADD_IMM:
13478                 return OP_AMD64_ADD_MEMBASE_IMM;
13479         case OP_SUB_IMM:
13480         case OP_LSUB_IMM:
13481                 return OP_AMD64_SUB_MEMBASE_IMM;
13482         case OP_AND_IMM:
13483         case OP_LAND_IMM:
13484                 return OP_AMD64_AND_MEMBASE_IMM;
13485         case OP_OR_IMM:
13486         case OP_LOR_IMM:
13487                 return OP_AMD64_OR_MEMBASE_IMM;
13488         case OP_XOR_IMM:
13489         case OP_LXOR_IMM:
13490                 return OP_AMD64_XOR_MEMBASE_IMM;
13491         case OP_MOVE:
13492                 return OP_NOP;
13493         }
13494 #endif
13495
13496         return -1;
13497 }
13498
13499 static inline int
13500 op_to_op_store_membase (int store_opcode, int opcode)
13501 {
13502 #if defined(TARGET_X86) || defined(TARGET_AMD64)
13503         switch (opcode) {
13504         case OP_ICEQ:
13505                 if (store_opcode == OP_STOREI1_MEMBASE_REG)
13506                         return OP_X86_SETEQ_MEMBASE;
13507         case OP_CNE:
13508                 if (store_opcode == OP_STOREI1_MEMBASE_REG)
13509                         return OP_X86_SETNE_MEMBASE;
13510         }
13511 #endif
13512
13513         return -1;
13514 }
13515
13516 static inline int
13517 op_to_op_src1_membase (MonoCompile *cfg, int load_opcode, int opcode)
13518 {
13519 #ifdef TARGET_X86
13520         /* FIXME: This has sign extension issues */
13521         /*
13522         if ((opcode == OP_ICOMPARE_IMM) && (load_opcode == OP_LOADU1_MEMBASE))
13523                 return OP_X86_COMPARE_MEMBASE8_IMM;
13524         */
13525
13526         if (!((load_opcode == OP_LOAD_MEMBASE) || (load_opcode == OP_LOADI4_MEMBASE) || (load_opcode == OP_LOADU4_MEMBASE)))
13527                 return -1;
13528
13529         switch (opcode) {
13530         case OP_X86_PUSH:
13531                 return OP_X86_PUSH_MEMBASE;
13532         case OP_COMPARE_IMM:
13533         case OP_ICOMPARE_IMM:
13534                 return OP_X86_COMPARE_MEMBASE_IMM;
13535         case OP_COMPARE:
13536         case OP_ICOMPARE:
13537                 return OP_X86_COMPARE_MEMBASE_REG;
13538         }
13539 #endif
13540
13541 #ifdef TARGET_AMD64
13542         /* FIXME: This has sign extension issues */
13543         /*
13544         if ((opcode == OP_ICOMPARE_IMM) && (load_opcode == OP_LOADU1_MEMBASE))
13545                 return OP_X86_COMPARE_MEMBASE8_IMM;
13546         */
13547
13548         switch (opcode) {
13549         case OP_X86_PUSH:
13550                 if ((load_opcode == OP_LOAD_MEMBASE && !cfg->backend->ilp32) || (load_opcode == OP_LOADI8_MEMBASE))
13551                         return OP_X86_PUSH_MEMBASE;
13552                 break;
13553                 /* FIXME: This only works for 32 bit immediates
13554         case OP_COMPARE_IMM:
13555         case OP_LCOMPARE_IMM:
13556                 if ((load_opcode == OP_LOAD_MEMBASE) || (load_opcode == OP_LOADI8_MEMBASE))
13557                         return OP_AMD64_COMPARE_MEMBASE_IMM;
13558                 */
13559         case OP_ICOMPARE_IMM:
13560                 if ((load_opcode == OP_LOADI4_MEMBASE) || (load_opcode == OP_LOADU4_MEMBASE))
13561                         return OP_AMD64_ICOMPARE_MEMBASE_IMM;
13562                 break;
13563         case OP_COMPARE:
13564         case OP_LCOMPARE:
13565                 if (cfg->backend->ilp32 && load_opcode == OP_LOAD_MEMBASE)
13566                         return OP_AMD64_ICOMPARE_MEMBASE_REG;
13567                 if ((load_opcode == OP_LOAD_MEMBASE && !cfg->backend->ilp32) || (load_opcode == OP_LOADI8_MEMBASE))
13568                         return OP_AMD64_COMPARE_MEMBASE_REG;
13569                 break;
13570         case OP_ICOMPARE:
13571                 if ((load_opcode == OP_LOADI4_MEMBASE) || (load_opcode == OP_LOADU4_MEMBASE))
13572                         return OP_AMD64_ICOMPARE_MEMBASE_REG;
13573                 break;
13574         }
13575 #endif
13576
13577         return -1;
13578 }
13579
13580 static inline int
13581 op_to_op_src2_membase (MonoCompile *cfg, int load_opcode, int opcode)
13582 {
13583 #ifdef TARGET_X86
13584         if (!((load_opcode == OP_LOAD_MEMBASE) || (load_opcode == OP_LOADI4_MEMBASE) || (load_opcode == OP_LOADU4_MEMBASE)))
13585                 return -1;
13586         
13587         switch (opcode) {
13588         case OP_COMPARE:
13589         case OP_ICOMPARE:
13590                 return OP_X86_COMPARE_REG_MEMBASE;
13591         case OP_IADD:
13592                 return OP_X86_ADD_REG_MEMBASE;
13593         case OP_ISUB:
13594                 return OP_X86_SUB_REG_MEMBASE;
13595         case OP_IAND:
13596                 return OP_X86_AND_REG_MEMBASE;
13597         case OP_IOR:
13598                 return OP_X86_OR_REG_MEMBASE;
13599         case OP_IXOR:
13600                 return OP_X86_XOR_REG_MEMBASE;
13601         }
13602 #endif
13603
13604 #ifdef TARGET_AMD64
13605         if ((load_opcode == OP_LOADI4_MEMBASE) || (load_opcode == OP_LOADU4_MEMBASE) || (load_opcode == OP_LOAD_MEMBASE && cfg->backend->ilp32)) {
13606                 switch (opcode) {
13607                 case OP_ICOMPARE:
13608                         return OP_AMD64_ICOMPARE_REG_MEMBASE;
13609                 case OP_IADD:
13610                         return OP_X86_ADD_REG_MEMBASE;
13611                 case OP_ISUB:
13612                         return OP_X86_SUB_REG_MEMBASE;
13613                 case OP_IAND:
13614                         return OP_X86_AND_REG_MEMBASE;
13615                 case OP_IOR:
13616                         return OP_X86_OR_REG_MEMBASE;
13617                 case OP_IXOR:
13618                         return OP_X86_XOR_REG_MEMBASE;
13619                 }
13620         } else if ((load_opcode == OP_LOADI8_MEMBASE) || (load_opcode == OP_LOAD_MEMBASE && !cfg->backend->ilp32)) {
13621                 switch (opcode) {
13622                 case OP_COMPARE:
13623                 case OP_LCOMPARE:
13624                         return OP_AMD64_COMPARE_REG_MEMBASE;
13625                 case OP_LADD:
13626                         return OP_AMD64_ADD_REG_MEMBASE;
13627                 case OP_LSUB:
13628                         return OP_AMD64_SUB_REG_MEMBASE;
13629                 case OP_LAND:
13630                         return OP_AMD64_AND_REG_MEMBASE;
13631                 case OP_LOR:
13632                         return OP_AMD64_OR_REG_MEMBASE;
13633                 case OP_LXOR:
13634                         return OP_AMD64_XOR_REG_MEMBASE;
13635                 }
13636         }
13637 #endif
13638
13639         return -1;
13640 }
13641
13642 int
13643 mono_op_to_op_imm_noemul (int opcode)
13644 {
13645         switch (opcode) {
13646 #if SIZEOF_REGISTER == 4 && !defined(MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS)
13647         case OP_LSHR:
13648         case OP_LSHL:
13649         case OP_LSHR_UN:
13650                 return -1;
13651 #endif
13652 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV)
13653         case OP_IDIV:
13654         case OP_IDIV_UN:
13655         case OP_IREM:
13656         case OP_IREM_UN:
13657                 return -1;
13658 #endif
13659 #if defined(MONO_ARCH_EMULATE_MUL_DIV)
13660         case OP_IMUL:
13661                 return -1;
13662 #endif
13663         default:
13664                 return mono_op_to_op_imm (opcode);
13665         }
13666 }
13667
13668 /**
13669  * mono_handle_global_vregs:
13670  *
13671  *   Make vregs used in more than one bblock 'global', i.e. allocate a variable
13672  * for them.
13673  */
13674 void
13675 mono_handle_global_vregs (MonoCompile *cfg)
13676 {
13677         gint32 *vreg_to_bb;
13678         MonoBasicBlock *bb;
13679         int i, pos;
13680
13681         vreg_to_bb = mono_mempool_alloc0 (cfg->mempool, sizeof (gint32*) * cfg->next_vreg + 1);
13682
13683 #ifdef MONO_ARCH_SIMD_INTRINSICS
13684         if (cfg->uses_simd_intrinsics)
13685                 mono_simd_simplify_indirection (cfg);
13686 #endif
13687
13688         /* Find local vregs used in more than one bb */
13689         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
13690                 MonoInst *ins = bb->code;       
13691                 int block_num = bb->block_num;
13692
13693                 if (cfg->verbose_level > 2)
13694                         printf ("\nHANDLE-GLOBAL-VREGS BLOCK %d:\n", bb->block_num);
13695
13696                 cfg->cbb = bb;
13697                 for (; ins; ins = ins->next) {
13698                         const char *spec = INS_INFO (ins->opcode);
13699                         int regtype = 0, regindex;
13700                         gint32 prev_bb;
13701
13702                         if (G_UNLIKELY (cfg->verbose_level > 2))
13703                                 mono_print_ins (ins);
13704
13705                         g_assert (ins->opcode >= MONO_CEE_LAST);
13706
13707                         for (regindex = 0; regindex < 4; regindex ++) {
13708                                 int vreg = 0;
13709
13710                                 if (regindex == 0) {
13711                                         regtype = spec [MONO_INST_DEST];
13712                                         if (regtype == ' ')
13713                                                 continue;
13714                                         vreg = ins->dreg;
13715                                 } else if (regindex == 1) {
13716                                         regtype = spec [MONO_INST_SRC1];
13717                                         if (regtype == ' ')
13718                                                 continue;
13719                                         vreg = ins->sreg1;
13720                                 } else if (regindex == 2) {
13721                                         regtype = spec [MONO_INST_SRC2];
13722                                         if (regtype == ' ')
13723                                                 continue;
13724                                         vreg = ins->sreg2;
13725                                 } else if (regindex == 3) {
13726                                         regtype = spec [MONO_INST_SRC3];
13727                                         if (regtype == ' ')
13728                                                 continue;
13729                                         vreg = ins->sreg3;
13730                                 }
13731
13732 #if SIZEOF_REGISTER == 4
13733                                 /* In the LLVM case, the long opcodes are not decomposed */
13734                                 if (regtype == 'l' && !COMPILE_LLVM (cfg)) {
13735                                         /*
13736                                          * Since some instructions reference the original long vreg,
13737                                          * and some reference the two component vregs, it is quite hard
13738                                          * to determine when it needs to be global. So be conservative.
13739                                          */
13740                                         if (!get_vreg_to_inst (cfg, vreg)) {
13741                                                 mono_compile_create_var_for_vreg (cfg, &mono_defaults.int64_class->byval_arg, OP_LOCAL, vreg);
13742
13743                                                 if (cfg->verbose_level > 2)
13744                                                         printf ("LONG VREG R%d made global.\n", vreg);
13745                                         }
13746
13747                                         /*
13748                                          * Make the component vregs volatile since the optimizations can
13749                                          * get confused otherwise.
13750                                          */
13751                                         get_vreg_to_inst (cfg, vreg + 1)->flags |= MONO_INST_VOLATILE;
13752                                         get_vreg_to_inst (cfg, vreg + 2)->flags |= MONO_INST_VOLATILE;
13753                                 }
13754 #endif
13755
13756                                 g_assert (vreg != -1);
13757
13758                                 prev_bb = vreg_to_bb [vreg];
13759                                 if (prev_bb == 0) {
13760                                         /* 0 is a valid block num */
13761                                         vreg_to_bb [vreg] = block_num + 1;
13762                                 } else if ((prev_bb != block_num + 1) && (prev_bb != -1)) {
13763                                         if (((regtype == 'i' && (vreg < MONO_MAX_IREGS))) || (regtype == 'f' && (vreg < MONO_MAX_FREGS)))
13764                                                 continue;
13765
13766                                         if (!get_vreg_to_inst (cfg, vreg)) {
13767                                                 if (G_UNLIKELY (cfg->verbose_level > 2))
13768                                                         printf ("VREG R%d used in BB%d and BB%d made global.\n", vreg, vreg_to_bb [vreg], block_num);
13769
13770                                                 switch (regtype) {
13771                                                 case 'i':
13772                                                         if (vreg_is_ref (cfg, vreg))
13773                                                                 mono_compile_create_var_for_vreg (cfg, &mono_defaults.object_class->byval_arg, OP_LOCAL, vreg);
13774                                                         else
13775                                                                 mono_compile_create_var_for_vreg (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL, vreg);
13776                                                         break;
13777                                                 case 'l':
13778                                                         mono_compile_create_var_for_vreg (cfg, &mono_defaults.int64_class->byval_arg, OP_LOCAL, vreg);
13779                                                         break;
13780                                                 case 'f':
13781                                                         mono_compile_create_var_for_vreg (cfg, &mono_defaults.double_class->byval_arg, OP_LOCAL, vreg);
13782                                                         break;
13783                                                 case 'v':
13784                                                         mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, vreg);
13785                                                         break;
13786                                                 default:
13787                                                         g_assert_not_reached ();
13788                                                 }
13789                                         }
13790
13791                                         /* Flag as having been used in more than one bb */
13792                                         vreg_to_bb [vreg] = -1;
13793                                 }
13794                         }
13795                 }
13796         }
13797
13798         /* If a variable is used in only one bblock, convert it into a local vreg */
13799         for (i = 0; i < cfg->num_varinfo; i++) {
13800                 MonoInst *var = cfg->varinfo [i];
13801                 MonoMethodVar *vmv = MONO_VARINFO (cfg, i);
13802
13803                 switch (var->type) {
13804                 case STACK_I4:
13805                 case STACK_OBJ:
13806                 case STACK_PTR:
13807                 case STACK_MP:
13808                 case STACK_VTYPE:
13809 #if SIZEOF_REGISTER == 8
13810                 case STACK_I8:
13811 #endif
13812 #if !defined(TARGET_X86)
13813                 /* Enabling this screws up the fp stack on x86 */
13814                 case STACK_R8:
13815 #endif
13816                         if (mono_arch_is_soft_float ())
13817                                 break;
13818
13819                         /* Arguments are implicitly global */
13820                         /* Putting R4 vars into registers doesn't work currently */
13821                         /* The gsharedvt vars are implicitly referenced by ldaddr opcodes, but those opcodes are only generated later */
13822                         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) {
13823                                 /* 
13824                                  * Make that the variable's liveness interval doesn't contain a call, since
13825                                  * that would cause the lvreg to be spilled, making the whole optimization
13826                                  * useless.
13827                                  */
13828                                 /* This is too slow for JIT compilation */
13829 #if 0
13830                                 if (cfg->compile_aot && vreg_to_bb [var->dreg]) {
13831                                         MonoInst *ins;
13832                                         int def_index, call_index, ins_index;
13833                                         gboolean spilled = FALSE;
13834
13835                                         def_index = -1;
13836                                         call_index = -1;
13837                                         ins_index = 0;
13838                                         for (ins = vreg_to_bb [var->dreg]->code; ins; ins = ins->next) {
13839                                                 const char *spec = INS_INFO (ins->opcode);
13840
13841                                                 if ((spec [MONO_INST_DEST] != ' ') && (ins->dreg == var->dreg))
13842                                                         def_index = ins_index;
13843
13844                                                 if (((spec [MONO_INST_SRC1] != ' ') && (ins->sreg1 == var->dreg)) ||
13845                                                         ((spec [MONO_INST_SRC1] != ' ') && (ins->sreg1 == var->dreg))) {
13846                                                         if (call_index > def_index) {
13847                                                                 spilled = TRUE;
13848                                                                 break;
13849                                                         }
13850                                                 }
13851
13852                                                 if (MONO_IS_CALL (ins))
13853                                                         call_index = ins_index;
13854
13855                                                 ins_index ++;
13856                                         }
13857
13858                                         if (spilled)
13859                                                 break;
13860                                 }
13861 #endif
13862
13863                                 if (G_UNLIKELY (cfg->verbose_level > 2))
13864                                         printf ("CONVERTED R%d(%d) TO VREG.\n", var->dreg, vmv->idx);
13865                                 var->flags |= MONO_INST_IS_DEAD;
13866                                 cfg->vreg_to_inst [var->dreg] = NULL;
13867                         }
13868                         break;
13869                 }
13870         }
13871
13872         /* 
13873          * Compress the varinfo and vars tables so the liveness computation is faster and
13874          * takes up less space.
13875          */
13876         pos = 0;
13877         for (i = 0; i < cfg->num_varinfo; ++i) {
13878                 MonoInst *var = cfg->varinfo [i];
13879                 if (pos < i && cfg->locals_start == i)
13880                         cfg->locals_start = pos;
13881                 if (!(var->flags & MONO_INST_IS_DEAD)) {
13882                         if (pos < i) {
13883                                 cfg->varinfo [pos] = cfg->varinfo [i];
13884                                 cfg->varinfo [pos]->inst_c0 = pos;
13885                                 memcpy (&cfg->vars [pos], &cfg->vars [i], sizeof (MonoMethodVar));
13886                                 cfg->vars [pos].idx = pos;
13887 #if SIZEOF_REGISTER == 4
13888                                 if (cfg->varinfo [pos]->type == STACK_I8) {
13889                                         /* Modify the two component vars too */
13890                                         MonoInst *var1;
13891
13892                                         var1 = get_vreg_to_inst (cfg, cfg->varinfo [pos]->dreg + 1);
13893                                         var1->inst_c0 = pos;
13894                                         var1 = get_vreg_to_inst (cfg, cfg->varinfo [pos]->dreg + 2);
13895                                         var1->inst_c0 = pos;
13896                                 }
13897 #endif
13898                         }
13899                         pos ++;
13900                 }
13901         }
13902         cfg->num_varinfo = pos;
13903         if (cfg->locals_start > cfg->num_varinfo)
13904                 cfg->locals_start = cfg->num_varinfo;
13905 }
13906
13907 /**
13908  * mono_spill_global_vars:
13909  *
13910  *   Generate spill code for variables which are not allocated to registers, 
13911  * and replace vregs with their allocated hregs. *need_local_opts is set to TRUE if
13912  * code is generated which could be optimized by the local optimization passes.
13913  */
13914 void
13915 mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts)
13916 {
13917         MonoBasicBlock *bb;
13918         char spec2 [16];
13919         int orig_next_vreg;
13920         guint32 *vreg_to_lvreg;
13921         guint32 *lvregs;
13922         guint32 i, lvregs_len;
13923         gboolean dest_has_lvreg = FALSE;
13924         guint32 stacktypes [128];
13925         MonoInst **live_range_start, **live_range_end;
13926         MonoBasicBlock **live_range_start_bb, **live_range_end_bb;
13927         int *gsharedvt_vreg_to_idx = NULL;
13928
13929         *need_local_opts = FALSE;
13930
13931         memset (spec2, 0, sizeof (spec2));
13932
13933         /* FIXME: Move this function to mini.c */
13934         stacktypes ['i'] = STACK_PTR;
13935         stacktypes ['l'] = STACK_I8;
13936         stacktypes ['f'] = STACK_R8;
13937 #ifdef MONO_ARCH_SIMD_INTRINSICS
13938         stacktypes ['x'] = STACK_VTYPE;
13939 #endif
13940
13941 #if SIZEOF_REGISTER == 4
13942         /* Create MonoInsts for longs */
13943         for (i = 0; i < cfg->num_varinfo; i++) {
13944                 MonoInst *ins = cfg->varinfo [i];
13945
13946                 if ((ins->opcode != OP_REGVAR) && !(ins->flags & MONO_INST_IS_DEAD)) {
13947                         switch (ins->type) {
13948                         case STACK_R8:
13949                         case STACK_I8: {
13950                                 MonoInst *tree;
13951
13952                                 if (ins->type == STACK_R8 && !COMPILE_SOFT_FLOAT (cfg))
13953                                         break;
13954
13955                                 g_assert (ins->opcode == OP_REGOFFSET);
13956
13957                                 tree = get_vreg_to_inst (cfg, ins->dreg + 1);
13958                                 g_assert (tree);
13959                                 tree->opcode = OP_REGOFFSET;
13960                                 tree->inst_basereg = ins->inst_basereg;
13961                                 tree->inst_offset = ins->inst_offset + MINI_LS_WORD_OFFSET;
13962
13963                                 tree = get_vreg_to_inst (cfg, ins->dreg + 2);
13964                                 g_assert (tree);
13965                                 tree->opcode = OP_REGOFFSET;
13966                                 tree->inst_basereg = ins->inst_basereg;
13967                                 tree->inst_offset = ins->inst_offset + MINI_MS_WORD_OFFSET;
13968                                 break;
13969                         }
13970                         default:
13971                                 break;
13972                         }
13973                 }
13974         }
13975 #endif
13976
13977         if (cfg->compute_gc_maps) {
13978                 /* registers need liveness info even for !non refs */
13979                 for (i = 0; i < cfg->num_varinfo; i++) {
13980                         MonoInst *ins = cfg->varinfo [i];
13981
13982                         if (ins->opcode == OP_REGVAR)
13983                                 ins->flags |= MONO_INST_GC_TRACK;
13984                 }
13985         }
13986
13987         if (cfg->gsharedvt) {
13988                 gsharedvt_vreg_to_idx = mono_mempool_alloc0 (cfg->mempool, sizeof (int) * cfg->next_vreg);
13989
13990                 for (i = 0; i < cfg->num_varinfo; ++i) {
13991                         MonoInst *ins = cfg->varinfo [i];
13992                         int idx;
13993
13994                         if (mini_is_gsharedvt_variable_type (ins->inst_vtype)) {
13995                                 if (i >= cfg->locals_start) {
13996                                         /* Local */
13997                                         idx = get_gsharedvt_info_slot (cfg, ins->inst_vtype, MONO_RGCTX_INFO_LOCAL_OFFSET);
13998                                         gsharedvt_vreg_to_idx [ins->dreg] = idx + 1;
13999                                         ins->opcode = OP_GSHAREDVT_LOCAL;
14000                                         ins->inst_imm = idx;
14001                                 } else {
14002                                         /* Arg */
14003                                         gsharedvt_vreg_to_idx [ins->dreg] = -1;
14004                                         ins->opcode = OP_GSHAREDVT_ARG_REGOFFSET;
14005                                 }
14006                         }
14007                 }
14008         }
14009                 
14010         /* FIXME: widening and truncation */
14011
14012         /*
14013          * As an optimization, when a variable allocated to the stack is first loaded into 
14014          * an lvreg, we will remember the lvreg and use it the next time instead of loading
14015          * the variable again.
14016          */
14017         orig_next_vreg = cfg->next_vreg;
14018         vreg_to_lvreg = mono_mempool_alloc0 (cfg->mempool, sizeof (guint32) * cfg->next_vreg);
14019         lvregs = mono_mempool_alloc (cfg->mempool, sizeof (guint32) * 1024);
14020         lvregs_len = 0;
14021
14022         /* 
14023          * These arrays contain the first and last instructions accessing a given
14024          * variable.
14025          * Since we emit bblocks in the same order we process them here, and we
14026          * don't split live ranges, these will precisely describe the live range of
14027          * the variable, i.e. the instruction range where a valid value can be found
14028          * in the variables location.
14029          * The live range is computed using the liveness info computed by the liveness pass.
14030          * We can't use vmv->range, since that is an abstract live range, and we need
14031          * one which is instruction precise.
14032          * FIXME: Variables used in out-of-line bblocks have a hole in their live range.
14033          */
14034         /* FIXME: Only do this if debugging info is requested */
14035         live_range_start = g_new0 (MonoInst*, cfg->next_vreg);
14036         live_range_end = g_new0 (MonoInst*, cfg->next_vreg);
14037         live_range_start_bb = g_new (MonoBasicBlock*, cfg->next_vreg);
14038         live_range_end_bb = g_new (MonoBasicBlock*, cfg->next_vreg);
14039         
14040         /* Add spill loads/stores */
14041         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
14042                 MonoInst *ins;
14043
14044                 if (cfg->verbose_level > 2)
14045                         printf ("\nSPILL BLOCK %d:\n", bb->block_num);
14046
14047                 /* Clear vreg_to_lvreg array */
14048                 for (i = 0; i < lvregs_len; i++)
14049                         vreg_to_lvreg [lvregs [i]] = 0;
14050                 lvregs_len = 0;
14051
14052                 cfg->cbb = bb;
14053                 MONO_BB_FOR_EACH_INS (bb, ins) {
14054                         const char *spec = INS_INFO (ins->opcode);
14055                         int regtype, srcindex, sreg, tmp_reg, prev_dreg, num_sregs;
14056                         gboolean store, no_lvreg;
14057                         int sregs [MONO_MAX_SRC_REGS];
14058
14059                         if (G_UNLIKELY (cfg->verbose_level > 2))
14060                                 mono_print_ins (ins);
14061
14062                         if (ins->opcode == OP_NOP)
14063                                 continue;
14064
14065                         /* 
14066                          * We handle LDADDR here as well, since it can only be decomposed
14067                          * when variable addresses are known.
14068                          */
14069                         if (ins->opcode == OP_LDADDR) {
14070                                 MonoInst *var = ins->inst_p0;
14071
14072                                 if (var->opcode == OP_VTARG_ADDR) {
14073                                         /* Happens on SPARC/S390 where vtypes are passed by reference */
14074                                         MonoInst *vtaddr = var->inst_left;
14075                                         if (vtaddr->opcode == OP_REGVAR) {
14076                                                 ins->opcode = OP_MOVE;
14077                                                 ins->sreg1 = vtaddr->dreg;
14078                                         }
14079                                         else if (var->inst_left->opcode == OP_REGOFFSET) {
14080                                                 ins->opcode = OP_LOAD_MEMBASE;
14081                                                 ins->inst_basereg = vtaddr->inst_basereg;
14082                                                 ins->inst_offset = vtaddr->inst_offset;
14083                                         } else
14084                                                 NOT_IMPLEMENTED;
14085                                 } else if (cfg->gsharedvt && gsharedvt_vreg_to_idx [var->dreg] < 0) {
14086                                         /* gsharedvt arg passed by ref */
14087                                         g_assert (var->opcode == OP_GSHAREDVT_ARG_REGOFFSET);
14088
14089                                         ins->opcode = OP_LOAD_MEMBASE;
14090                                         ins->inst_basereg = var->inst_basereg;
14091                                         ins->inst_offset = var->inst_offset;
14092                                 } else if (cfg->gsharedvt && gsharedvt_vreg_to_idx [var->dreg]) {
14093                                         MonoInst *load, *load2, *load3;
14094                                         int idx = gsharedvt_vreg_to_idx [var->dreg] - 1;
14095                                         int reg1, reg2, reg3;
14096                                         MonoInst *info_var = cfg->gsharedvt_info_var;
14097                                         MonoInst *locals_var = cfg->gsharedvt_locals_var;
14098
14099                                         /*
14100                                          * gsharedvt local.
14101                                          * Compute the address of the local as gsharedvt_locals_var + gsharedvt_info_var->locals_offsets [idx].
14102                                          */
14103
14104                                         g_assert (var->opcode == OP_GSHAREDVT_LOCAL);
14105
14106                                         g_assert (info_var);
14107                                         g_assert (locals_var);
14108
14109                                         /* Mark the instruction used to compute the locals var as used */
14110                                         cfg->gsharedvt_locals_var_ins = NULL;
14111
14112                                         /* Load the offset */
14113                                         if (info_var->opcode == OP_REGOFFSET) {
14114                                                 reg1 = alloc_ireg (cfg);
14115                                                 NEW_LOAD_MEMBASE (cfg, load, OP_LOAD_MEMBASE, reg1, info_var->inst_basereg, info_var->inst_offset);
14116                                         } else if (info_var->opcode == OP_REGVAR) {
14117                                                 load = NULL;
14118                                                 reg1 = info_var->dreg;
14119                                         } else {
14120                                                 g_assert_not_reached ();
14121                                         }
14122                                         reg2 = alloc_ireg (cfg);
14123                                         NEW_LOAD_MEMBASE (cfg, load2, OP_LOADI4_MEMBASE, reg2, reg1, MONO_STRUCT_OFFSET (MonoGSharedVtMethodRuntimeInfo, entries) + (idx * sizeof (gpointer)));
14124                                         /* Load the locals area address */
14125                                         reg3 = alloc_ireg (cfg);
14126                                         if (locals_var->opcode == OP_REGOFFSET) {
14127                                                 NEW_LOAD_MEMBASE (cfg, load3, OP_LOAD_MEMBASE, reg3, locals_var->inst_basereg, locals_var->inst_offset);
14128                                         } else if (locals_var->opcode == OP_REGVAR) {
14129                                                 NEW_UNALU (cfg, load3, OP_MOVE, reg3, locals_var->dreg);
14130                                         } else {
14131                                                 g_assert_not_reached ();
14132                                         }
14133                                         /* Compute the address */
14134                                         ins->opcode = OP_PADD;
14135                                         ins->sreg1 = reg3;
14136                                         ins->sreg2 = reg2;
14137
14138                                         mono_bblock_insert_before_ins (bb, ins, load3);
14139                                         mono_bblock_insert_before_ins (bb, load3, load2);
14140                                         if (load)
14141                                                 mono_bblock_insert_before_ins (bb, load2, load);
14142                                 } else {
14143                                         g_assert (var->opcode == OP_REGOFFSET);
14144
14145                                         ins->opcode = OP_ADD_IMM;
14146                                         ins->sreg1 = var->inst_basereg;
14147                                         ins->inst_imm = var->inst_offset;
14148                                 }
14149
14150                                 *need_local_opts = TRUE;
14151                                 spec = INS_INFO (ins->opcode);
14152                         }
14153
14154                         if (ins->opcode < MONO_CEE_LAST) {
14155                                 mono_print_ins (ins);
14156                                 g_assert_not_reached ();
14157                         }
14158
14159                         /*
14160                          * Store opcodes have destbasereg in the dreg, but in reality, it is an
14161                          * src register.
14162                          * FIXME:
14163                          */
14164                         if (MONO_IS_STORE_MEMBASE (ins)) {
14165                                 tmp_reg = ins->dreg;
14166                                 ins->dreg = ins->sreg2;
14167                                 ins->sreg2 = tmp_reg;
14168                                 store = TRUE;
14169
14170                                 spec2 [MONO_INST_DEST] = ' ';
14171                                 spec2 [MONO_INST_SRC1] = spec [MONO_INST_SRC1];
14172                                 spec2 [MONO_INST_SRC2] = spec [MONO_INST_DEST];
14173                                 spec2 [MONO_INST_SRC3] = ' ';
14174                                 spec = spec2;
14175                         } else if (MONO_IS_STORE_MEMINDEX (ins))
14176                                 g_assert_not_reached ();
14177                         else
14178                                 store = FALSE;
14179                         no_lvreg = FALSE;
14180
14181                         if (G_UNLIKELY (cfg->verbose_level > 2)) {
14182                                 printf ("\t %.3s %d", spec, ins->dreg);
14183                                 num_sregs = mono_inst_get_src_registers (ins, sregs);
14184                                 for (srcindex = 0; srcindex < num_sregs; ++srcindex)
14185                                         printf (" %d", sregs [srcindex]);
14186                                 printf ("\n");
14187                         }
14188
14189                         /***************/
14190                         /*    DREG     */
14191                         /***************/
14192                         regtype = spec [MONO_INST_DEST];
14193                         g_assert (((ins->dreg == -1) && (regtype == ' ')) || ((ins->dreg != -1) && (regtype != ' ')));
14194                         prev_dreg = -1;
14195
14196                         if ((ins->dreg != -1) && get_vreg_to_inst (cfg, ins->dreg)) {
14197                                 MonoInst *var = get_vreg_to_inst (cfg, ins->dreg);
14198                                 MonoInst *store_ins;
14199                                 int store_opcode;
14200                                 MonoInst *def_ins = ins;
14201                                 int dreg = ins->dreg; /* The original vreg */
14202
14203                                 store_opcode = mono_type_to_store_membase (cfg, var->inst_vtype);
14204
14205                                 if (var->opcode == OP_REGVAR) {
14206                                         ins->dreg = var->dreg;
14207                                 } 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)) {
14208                                         /* 
14209                                          * Instead of emitting a load+store, use a _membase opcode.
14210                                          */
14211                                         g_assert (var->opcode == OP_REGOFFSET);
14212                                         if (ins->opcode == OP_MOVE) {
14213                                                 NULLIFY_INS (ins);
14214                                                 def_ins = NULL;
14215                                         } else {
14216                                                 ins->opcode = op_to_op_dest_membase (store_opcode, ins->opcode);
14217                                                 ins->inst_basereg = var->inst_basereg;
14218                                                 ins->inst_offset = var->inst_offset;
14219                                                 ins->dreg = -1;
14220                                         }
14221                                         spec = INS_INFO (ins->opcode);
14222                                 } else {
14223                                         guint32 lvreg;
14224
14225                                         g_assert (var->opcode == OP_REGOFFSET);
14226
14227                                         prev_dreg = ins->dreg;
14228
14229                                         /* Invalidate any previous lvreg for this vreg */
14230                                         vreg_to_lvreg [ins->dreg] = 0;
14231
14232                                         lvreg = 0;
14233
14234                                         if (COMPILE_SOFT_FLOAT (cfg) && store_opcode == OP_STORER8_MEMBASE_REG) {
14235                                                 regtype = 'l';
14236                                                 store_opcode = OP_STOREI8_MEMBASE_REG;
14237                                         }
14238
14239                                         ins->dreg = alloc_dreg (cfg, stacktypes [regtype]);
14240
14241 #if SIZEOF_REGISTER != 8
14242                                         if (regtype == 'l') {
14243                                                 NEW_STORE_MEMBASE (cfg, store_ins, OP_STOREI4_MEMBASE_REG, var->inst_basereg, var->inst_offset + MINI_LS_WORD_OFFSET, ins->dreg + 1);
14244                                                 mono_bblock_insert_after_ins (bb, ins, store_ins);
14245                                                 NEW_STORE_MEMBASE (cfg, store_ins, OP_STOREI4_MEMBASE_REG, var->inst_basereg, var->inst_offset + MINI_MS_WORD_OFFSET, ins->dreg + 2);
14246                                                 mono_bblock_insert_after_ins (bb, ins, store_ins);
14247                                                 def_ins = store_ins;
14248                                         }
14249                                         else
14250 #endif
14251                                         {
14252                                                 g_assert (store_opcode != OP_STOREV_MEMBASE);
14253
14254                                                 /* Try to fuse the store into the instruction itself */
14255                                                 /* FIXME: Add more instructions */
14256                                                 if (!lvreg && ((ins->opcode == OP_ICONST) || ((ins->opcode == OP_I8CONST) && (ins->inst_c0 == 0)))) {
14257                                                         ins->opcode = store_membase_reg_to_store_membase_imm (store_opcode);
14258                                                         ins->inst_imm = ins->inst_c0;
14259                                                         ins->inst_destbasereg = var->inst_basereg;
14260                                                         ins->inst_offset = var->inst_offset;
14261                                                         spec = INS_INFO (ins->opcode);
14262                                                 } else if (!lvreg && ((ins->opcode == OP_MOVE) || (ins->opcode == OP_FMOVE) || (ins->opcode == OP_LMOVE) || (ins->opcode == OP_RMOVE))) {
14263                                                         ins->opcode = store_opcode;
14264                                                         ins->inst_destbasereg = var->inst_basereg;
14265                                                         ins->inst_offset = var->inst_offset;
14266
14267                                                         no_lvreg = TRUE;
14268
14269                                                         tmp_reg = ins->dreg;
14270                                                         ins->dreg = ins->sreg2;
14271                                                         ins->sreg2 = tmp_reg;
14272                                                         store = TRUE;
14273
14274                                                         spec2 [MONO_INST_DEST] = ' ';
14275                                                         spec2 [MONO_INST_SRC1] = spec [MONO_INST_SRC1];
14276                                                         spec2 [MONO_INST_SRC2] = spec [MONO_INST_DEST];
14277                                                         spec2 [MONO_INST_SRC3] = ' ';
14278                                                         spec = spec2;
14279                                                 } else if (!lvreg && (op_to_op_store_membase (store_opcode, ins->opcode) != -1)) {
14280                                                         // FIXME: The backends expect the base reg to be in inst_basereg
14281                                                         ins->opcode = op_to_op_store_membase (store_opcode, ins->opcode);
14282                                                         ins->dreg = -1;
14283                                                         ins->inst_basereg = var->inst_basereg;
14284                                                         ins->inst_offset = var->inst_offset;
14285                                                         spec = INS_INFO (ins->opcode);
14286                                                 } else {
14287                                                         /* printf ("INS: "); mono_print_ins (ins); */
14288                                                         /* Create a store instruction */
14289                                                         NEW_STORE_MEMBASE (cfg, store_ins, store_opcode, var->inst_basereg, var->inst_offset, ins->dreg);
14290
14291                                                         /* Insert it after the instruction */
14292                                                         mono_bblock_insert_after_ins (bb, ins, store_ins);
14293
14294                                                         def_ins = store_ins;
14295
14296                                                         /* 
14297                                                          * We can't assign ins->dreg to var->dreg here, since the
14298                                                          * sregs could use it. So set a flag, and do it after
14299                                                          * the sregs.
14300                                                          */
14301                                                         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)))
14302                                                                 dest_has_lvreg = TRUE;
14303                                                 }
14304                                         }
14305                                 }
14306
14307                                 if (def_ins && !live_range_start [dreg]) {
14308                                         live_range_start [dreg] = def_ins;
14309                                         live_range_start_bb [dreg] = bb;
14310                                 }
14311
14312                                 if (cfg->compute_gc_maps && def_ins && (var->flags & MONO_INST_GC_TRACK)) {
14313                                         MonoInst *tmp;
14314
14315                                         MONO_INST_NEW (cfg, tmp, OP_GC_LIVENESS_DEF);
14316                                         tmp->inst_c1 = dreg;
14317                                         mono_bblock_insert_after_ins (bb, def_ins, tmp);
14318                                 }
14319                         }
14320
14321                         /************/
14322                         /*  SREGS   */
14323                         /************/
14324                         num_sregs = mono_inst_get_src_registers (ins, sregs);
14325                         for (srcindex = 0; srcindex < 3; ++srcindex) {
14326                                 regtype = spec [MONO_INST_SRC1 + srcindex];
14327                                 sreg = sregs [srcindex];
14328
14329                                 g_assert (((sreg == -1) && (regtype == ' ')) || ((sreg != -1) && (regtype != ' ')));
14330                                 if ((sreg != -1) && get_vreg_to_inst (cfg, sreg)) {
14331                                         MonoInst *var = get_vreg_to_inst (cfg, sreg);
14332                                         MonoInst *use_ins = ins;
14333                                         MonoInst *load_ins;
14334                                         guint32 load_opcode;
14335
14336                                         if (var->opcode == OP_REGVAR) {
14337                                                 sregs [srcindex] = var->dreg;
14338                                                 //mono_inst_set_src_registers (ins, sregs);
14339                                                 live_range_end [sreg] = use_ins;
14340                                                 live_range_end_bb [sreg] = bb;
14341
14342                                                 if (cfg->compute_gc_maps && var->dreg < orig_next_vreg && (var->flags & MONO_INST_GC_TRACK)) {
14343                                                         MonoInst *tmp;
14344
14345                                                         MONO_INST_NEW (cfg, tmp, OP_GC_LIVENESS_USE);
14346                                                         /* var->dreg is a hreg */
14347                                                         tmp->inst_c1 = sreg;
14348                                                         mono_bblock_insert_after_ins (bb, ins, tmp);
14349                                                 }
14350
14351                                                 continue;
14352                                         }
14353
14354                                         g_assert (var->opcode == OP_REGOFFSET);
14355                                                 
14356                                         load_opcode = mono_type_to_load_membase (cfg, var->inst_vtype);
14357
14358                                         g_assert (load_opcode != OP_LOADV_MEMBASE);
14359
14360                                         if (vreg_to_lvreg [sreg]) {
14361                                                 g_assert (vreg_to_lvreg [sreg] != -1);
14362
14363                                                 /* The variable is already loaded to an lvreg */
14364                                                 if (G_UNLIKELY (cfg->verbose_level > 2))
14365                                                         printf ("\t\tUse lvreg R%d for R%d.\n", vreg_to_lvreg [sreg], sreg);
14366                                                 sregs [srcindex] = vreg_to_lvreg [sreg];
14367                                                 //mono_inst_set_src_registers (ins, sregs);
14368                                                 continue;
14369                                         }
14370
14371                                         /* Try to fuse the load into the instruction */
14372                                         if ((srcindex == 0) && (op_to_op_src1_membase (cfg, load_opcode, ins->opcode) != -1)) {
14373                                                 ins->opcode = op_to_op_src1_membase (cfg, load_opcode, ins->opcode);
14374                                                 sregs [0] = var->inst_basereg;
14375                                                 //mono_inst_set_src_registers (ins, sregs);
14376                                                 ins->inst_offset = var->inst_offset;
14377                                         } else if ((srcindex == 1) && (op_to_op_src2_membase (cfg, load_opcode, ins->opcode) != -1)) {
14378                                                 ins->opcode = op_to_op_src2_membase (cfg, load_opcode, ins->opcode);
14379                                                 sregs [1] = var->inst_basereg;
14380                                                 //mono_inst_set_src_registers (ins, sregs);
14381                                                 ins->inst_offset = var->inst_offset;
14382                                         } else {
14383                                                 if (MONO_IS_REAL_MOVE (ins)) {
14384                                                         ins->opcode = OP_NOP;
14385                                                         sreg = ins->dreg;
14386                                                 } else {
14387                                                         //printf ("%d ", srcindex); mono_print_ins (ins);
14388
14389                                                         sreg = alloc_dreg (cfg, stacktypes [regtype]);
14390
14391                                                         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) {
14392                                                                 if (var->dreg == prev_dreg) {
14393                                                                         /*
14394                                                                          * sreg refers to the value loaded by the load
14395                                                                          * emitted below, but we need to use ins->dreg
14396                                                                          * since it refers to the store emitted earlier.
14397                                                                          */
14398                                                                         sreg = ins->dreg;
14399                                                                 }
14400                                                                 g_assert (sreg != -1);
14401                                                                 vreg_to_lvreg [var->dreg] = sreg;
14402                                                                 g_assert (lvregs_len < 1024);
14403                                                                 lvregs [lvregs_len ++] = var->dreg;
14404                                                         }
14405                                                 }
14406
14407                                                 sregs [srcindex] = sreg;
14408                                                 //mono_inst_set_src_registers (ins, sregs);
14409
14410 #if SIZEOF_REGISTER != 8
14411                                                 if (regtype == 'l') {
14412                                                         NEW_LOAD_MEMBASE (cfg, load_ins, OP_LOADI4_MEMBASE, sreg + 2, var->inst_basereg, var->inst_offset + MINI_MS_WORD_OFFSET);
14413                                                         mono_bblock_insert_before_ins (bb, ins, load_ins);
14414                                                         NEW_LOAD_MEMBASE (cfg, load_ins, OP_LOADI4_MEMBASE, sreg + 1, var->inst_basereg, var->inst_offset + MINI_LS_WORD_OFFSET);
14415                                                         mono_bblock_insert_before_ins (bb, ins, load_ins);
14416                                                         use_ins = load_ins;
14417                                                 }
14418                                                 else
14419 #endif
14420                                                 {
14421 #if SIZEOF_REGISTER == 4
14422                                                         g_assert (load_opcode != OP_LOADI8_MEMBASE);
14423 #endif
14424                                                         NEW_LOAD_MEMBASE (cfg, load_ins, load_opcode, sreg, var->inst_basereg, var->inst_offset);
14425                                                         mono_bblock_insert_before_ins (bb, ins, load_ins);
14426                                                         use_ins = load_ins;
14427                                                 }
14428                                         }
14429
14430                                         if (var->dreg < orig_next_vreg) {
14431                                                 live_range_end [var->dreg] = use_ins;
14432                                                 live_range_end_bb [var->dreg] = bb;
14433                                         }
14434
14435                                         if (cfg->compute_gc_maps && var->dreg < orig_next_vreg && (var->flags & MONO_INST_GC_TRACK)) {
14436                                                 MonoInst *tmp;
14437
14438                                                 MONO_INST_NEW (cfg, tmp, OP_GC_LIVENESS_USE);
14439                                                 tmp->inst_c1 = var->dreg;
14440                                                 mono_bblock_insert_after_ins (bb, ins, tmp);
14441                                         }
14442                                 }
14443                         }
14444                         mono_inst_set_src_registers (ins, sregs);
14445
14446                         if (dest_has_lvreg) {
14447                                 g_assert (ins->dreg != -1);
14448                                 vreg_to_lvreg [prev_dreg] = ins->dreg;
14449                                 g_assert (lvregs_len < 1024);
14450                                 lvregs [lvregs_len ++] = prev_dreg;
14451                                 dest_has_lvreg = FALSE;
14452                         }
14453
14454                         if (store) {
14455                                 tmp_reg = ins->dreg;
14456                                 ins->dreg = ins->sreg2;
14457                                 ins->sreg2 = tmp_reg;
14458                         }
14459
14460                         if (MONO_IS_CALL (ins)) {
14461                                 /* Clear vreg_to_lvreg array */
14462                                 for (i = 0; i < lvregs_len; i++)
14463                                         vreg_to_lvreg [lvregs [i]] = 0;
14464                                 lvregs_len = 0;
14465                         } else if (ins->opcode == OP_NOP) {
14466                                 ins->dreg = -1;
14467                                 MONO_INST_NULLIFY_SREGS (ins);
14468                         }
14469
14470                         if (cfg->verbose_level > 2)
14471                                 mono_print_ins_index (1, ins);
14472                 }
14473
14474                 /* Extend the live range based on the liveness info */
14475                 if (cfg->compute_precise_live_ranges && bb->live_out_set && bb->code) {
14476                         for (i = 0; i < cfg->num_varinfo; i ++) {
14477                                 MonoMethodVar *vi = MONO_VARINFO (cfg, i);
14478
14479                                 if (vreg_is_volatile (cfg, vi->vreg))
14480                                         /* The liveness info is incomplete */
14481                                         continue;
14482
14483                                 if (mono_bitset_test_fast (bb->live_in_set, i) && !live_range_start [vi->vreg]) {
14484                                         /* Live from at least the first ins of this bb */
14485                                         live_range_start [vi->vreg] = bb->code;
14486                                         live_range_start_bb [vi->vreg] = bb;
14487                                 }
14488
14489                                 if (mono_bitset_test_fast (bb->live_out_set, i)) {
14490                                         /* Live at least until the last ins of this bb */
14491                                         live_range_end [vi->vreg] = bb->last_ins;
14492                                         live_range_end_bb [vi->vreg] = bb;
14493                                 }
14494                         }
14495                 }
14496         }
14497         
14498         /*
14499          * Emit LIVERANGE_START/LIVERANGE_END opcodes, the backend will implement them
14500          * by storing the current native offset into MonoMethodVar->live_range_start/end.
14501          */
14502         if (cfg->backend->have_liverange_ops && cfg->compute_precise_live_ranges && cfg->comp_done & MONO_COMP_LIVENESS) {
14503                 for (i = 0; i < cfg->num_varinfo; ++i) {
14504                         int vreg = MONO_VARINFO (cfg, i)->vreg;
14505                         MonoInst *ins;
14506
14507                         if (live_range_start [vreg]) {
14508                                 MONO_INST_NEW (cfg, ins, OP_LIVERANGE_START);
14509                                 ins->inst_c0 = i;
14510                                 ins->inst_c1 = vreg;
14511                                 mono_bblock_insert_after_ins (live_range_start_bb [vreg], live_range_start [vreg], ins);
14512                         }
14513                         if (live_range_end [vreg]) {
14514                                 MONO_INST_NEW (cfg, ins, OP_LIVERANGE_END);
14515                                 ins->inst_c0 = i;
14516                                 ins->inst_c1 = vreg;
14517                                 if (live_range_end [vreg] == live_range_end_bb [vreg]->last_ins)
14518                                         mono_add_ins_to_end (live_range_end_bb [vreg], ins);
14519                                 else
14520                                         mono_bblock_insert_after_ins (live_range_end_bb [vreg], live_range_end [vreg], ins);
14521                         }
14522                 }
14523         }
14524
14525         if (cfg->gsharedvt_locals_var_ins) {
14526                 /* Nullify if unused */
14527                 cfg->gsharedvt_locals_var_ins->opcode = OP_PCONST;
14528                 cfg->gsharedvt_locals_var_ins->inst_imm = 0;
14529         }
14530
14531         g_free (live_range_start);
14532         g_free (live_range_end);
14533         g_free (live_range_start_bb);
14534         g_free (live_range_end_bb);
14535 }
14536
14537 /**
14538  * FIXME:
14539  * - use 'iadd' instead of 'int_add'
14540  * - handling ovf opcodes: decompose in method_to_ir.
14541  * - unify iregs/fregs
14542  *   -> partly done, the missing parts are:
14543  *   - a more complete unification would involve unifying the hregs as well, so
14544  *     code wouldn't need if (fp) all over the place. but that would mean the hregs
14545  *     would no longer map to the machine hregs, so the code generators would need to
14546  *     be modified. Also, on ia64 for example, niregs + nfregs > 256 -> bitmasks
14547  *     wouldn't work any more. Duplicating the code in mono_local_regalloc () into
14548  *     fp/non-fp branches speeds it up by about 15%.
14549  * - use sext/zext opcodes instead of shifts
14550  * - add OP_ICALL
14551  * - get rid of TEMPLOADs if possible and use vregs instead
14552  * - clean up usage of OP_P/OP_ opcodes
14553  * - cleanup usage of DUMMY_USE
14554  * - cleanup the setting of ins->type for MonoInst's which are pushed on the 
14555  *   stack
14556  * - set the stack type and allocate a dreg in the EMIT_NEW macros
14557  * - get rid of all the <foo>2 stuff when the new JIT is ready.
14558  * - make sure handle_stack_args () is called before the branch is emitted
14559  * - when the new IR is done, get rid of all unused stuff
14560  * - COMPARE/BEQ as separate instructions or unify them ?
14561  *   - keeping them separate allows specialized compare instructions like
14562  *     compare_imm, compare_membase
14563  *   - most back ends unify fp compare+branch, fp compare+ceq
14564  * - integrate mono_save_args into inline_method
14565  * - get rid of the empty bblocks created by MONO_EMIT_NEW_BRACH_BLOCK2
14566  * - handle long shift opts on 32 bit platforms somehow: they require 
14567  *   3 sregs (2 for arg1 and 1 for arg2)
14568  * - make byref a 'normal' type.
14569  * - use vregs for bb->out_stacks if possible, handle_global_vreg will make them a
14570  *   variable if needed.
14571  * - do not start a new IL level bblock when cfg->cbb is changed by a function call
14572  *   like inline_method.
14573  * - remove inlining restrictions
14574  * - fix LNEG and enable cfold of INEG
14575  * - generalize x86 optimizations like ldelema as a peephole optimization
14576  * - add store_mem_imm for amd64
14577  * - optimize the loading of the interruption flag in the managed->native wrappers
14578  * - avoid special handling of OP_NOP in passes
14579  * - move code inserting instructions into one function/macro.
14580  * - try a coalescing phase after liveness analysis
14581  * - add float -> vreg conversion + local optimizations on !x86
14582  * - figure out how to handle decomposed branches during optimizations, ie.
14583  *   compare+branch, op_jump_table+op_br etc.
14584  * - promote RuntimeXHandles to vregs
14585  * - vtype cleanups:
14586  *   - add a NEW_VARLOADA_VREG macro
14587  * - the vtype optimizations are blocked by the LDADDR opcodes generated for 
14588  *   accessing vtype fields.
14589  * - get rid of I8CONST on 64 bit platforms
14590  * - dealing with the increase in code size due to branches created during opcode
14591  *   decomposition:
14592  *   - use extended basic blocks
14593  *     - all parts of the JIT
14594  *     - handle_global_vregs () && local regalloc
14595  *   - avoid introducing global vregs during decomposition, like 'vtable' in isinst
14596  * - sources of increase in code size:
14597  *   - vtypes
14598  *   - long compares
14599  *   - isinst and castclass
14600  *   - lvregs not allocated to global registers even if used multiple times
14601  * - call cctors outside the JIT, to make -v output more readable and JIT timings more
14602  *   meaningful.
14603  * - check for fp stack leakage in other opcodes too. (-> 'exceptions' optimization)
14604  * - add all micro optimizations from the old JIT
14605  * - put tree optimizations into the deadce pass
14606  * - decompose op_start_handler/op_endfilter/op_endfinally earlier using an arch
14607  *   specific function.
14608  * - unify the float comparison opcodes with the other comparison opcodes, i.e.
14609  *   fcompare + branchCC.
14610  * - create a helper function for allocating a stack slot, taking into account 
14611  *   MONO_CFG_HAS_SPILLUP.
14612  * - merge r68207.
14613  * - merge the ia64 switch changes.
14614  * - optimize mono_regstate2_alloc_int/float.
14615  * - fix the pessimistic handling of variables accessed in exception handler blocks.
14616  * - need to write a tree optimization pass, but the creation of trees is difficult, i.e.
14617  *   parts of the tree could be separated by other instructions, killing the tree
14618  *   arguments, or stores killing loads etc. Also, should we fold loads into other
14619  *   instructions if the result of the load is used multiple times ?
14620  * - make the REM_IMM optimization in mini-x86.c arch-independent.
14621  * - LAST MERGE: 108395.
14622  * - when returning vtypes in registers, generate IR and append it to the end of the
14623  *   last bb instead of doing it in the epilog.
14624  * - change the store opcodes so they use sreg1 instead of dreg to store the base register.
14625  */
14626
14627 /*
14628
14629 NOTES
14630 -----
14631
14632 - When to decompose opcodes:
14633   - earlier: this makes some optimizations hard to implement, since the low level IR
14634   no longer contains the neccessary information. But it is easier to do.
14635   - later: harder to implement, enables more optimizations.
14636 - Branches inside bblocks:
14637   - created when decomposing complex opcodes. 
14638     - branches to another bblock: harmless, but not tracked by the branch 
14639       optimizations, so need to branch to a label at the start of the bblock.
14640     - branches to inside the same bblock: very problematic, trips up the local
14641       reg allocator. Can be fixed by spitting the current bblock, but that is a
14642       complex operation, since some local vregs can become global vregs etc.
14643 - Local/global vregs:
14644   - local vregs: temporary vregs used inside one bblock. Assigned to hregs by the
14645     local register allocator.
14646   - global vregs: used in more than one bblock. Have an associated MonoMethodVar
14647     structure, created by mono_create_var (). Assigned to hregs or the stack by
14648     the global register allocator.
14649 - When to do optimizations like alu->alu_imm:
14650   - earlier -> saves work later on since the IR will be smaller/simpler
14651   - later -> can work on more instructions
14652 - Handling of valuetypes:
14653   - When a vtype is pushed on the stack, a new temporary is created, an 
14654     instruction computing its address (LDADDR) is emitted and pushed on
14655     the stack. Need to optimize cases when the vtype is used immediately as in
14656     argument passing, stloc etc.
14657 - Instead of the to_end stuff in the old JIT, simply call the function handling
14658   the values on the stack before emitting the last instruction of the bb.
14659 */
14660
14661 #endif /* DISABLE_JIT */