[runtime] MonoError-ize mono_compile_method
[mono.git] / mono / mini / mini.c
1 /*
2  * mini.c: The new Mono code generator.
3  *
4  * Authors:
5  *   Paolo Molaro (lupus@ximian.com)
6  *   Dietmar Maurer (dietmar@ximian.com)
7  *
8  * Copyright 2002-2003 Ximian, Inc.
9  * Copyright 2003-2010 Novell, Inc.
10  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
11  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
12  */
13
14 #include <config.h>
15 #ifdef HAVE_ALLOCA_H
16 #include <alloca.h>
17 #endif
18 #ifdef HAVE_UNISTD_H
19 #include <unistd.h>
20 #endif
21 #include <math.h>
22 #ifdef HAVE_SYS_TIME_H
23 #include <sys/time.h>
24 #endif
25
26 #include <mono/utils/memcheck.h>
27
28 #include <mono/metadata/assembly.h>
29 #include <mono/metadata/loader.h>
30 #include <mono/metadata/tabledefs.h>
31 #include <mono/metadata/class.h>
32 #include <mono/metadata/object.h>
33 #include <mono/metadata/tokentype.h>
34 #include <mono/metadata/tabledefs.h>
35 #include <mono/metadata/threads.h>
36 #include <mono/metadata/appdomain.h>
37 #include <mono/metadata/debug-helpers.h>
38 #include "mono/metadata/profiler.h"
39 #include <mono/metadata/profiler-private.h>
40 #include <mono/metadata/mono-config.h>
41 #include <mono/metadata/environment.h>
42 #include <mono/metadata/mono-debug.h>
43 #include <mono/metadata/gc-internals.h>
44 #include <mono/metadata/threads-types.h>
45 #include <mono/metadata/verify.h>
46 #include <mono/metadata/verify-internals.h>
47 #include <mono/metadata/mempool-internals.h>
48 #include <mono/metadata/attach.h>
49 #include <mono/metadata/runtime.h>
50 #include <mono/utils/mono-math.h>
51 #include <mono/utils/mono-compiler.h>
52 #include <mono/utils/mono-counters.h>
53 #include <mono/utils/mono-error-internals.h>
54 #include <mono/utils/mono-logger-internals.h>
55 #include <mono/utils/mono-mmap.h>
56 #include <mono/utils/mono-path.h>
57 #include <mono/utils/mono-tls.h>
58 #include <mono/utils/mono-hwcap.h>
59 #include <mono/utils/dtrace.h>
60 #include <mono/utils/mono-threads.h>
61 #include <mono/io-layer/io-layer.h>
62
63 #include "mini.h"
64 #include "seq-points.h"
65 #include "tasklets.h"
66 #include <string.h>
67 #include <ctype.h>
68 #include "trace.h"
69 #include "version.h"
70 #include "ir-emit.h"
71
72 #include "jit-icalls.h"
73
74 #include "mini-gc.h"
75 #include "debugger-agent.h"
76 #include "llvm-runtime.h"
77 #include "mini-llvm.h"
78
79 MonoTraceSpec *mono_jit_trace_calls;
80 MonoMethodDesc *mono_inject_async_exc_method;
81 int mono_inject_async_exc_pos;
82 MonoMethodDesc *mono_break_at_bb_method;
83 int mono_break_at_bb_bb_num;
84 gboolean mono_do_x86_stack_align = TRUE;
85 gboolean mono_using_xdebug;
86
87 #define mono_jit_lock() mono_os_mutex_lock (&jit_mutex)
88 #define mono_jit_unlock() mono_os_mutex_unlock (&jit_mutex)
89 static mono_mutex_t jit_mutex;
90
91 MonoBackend *current_backend;
92
93 #ifndef DISABLE_JIT
94
95 gpointer
96 mono_realloc_native_code (MonoCompile *cfg)
97 {
98 #if defined(__default_codegen__)
99         return g_realloc (cfg->native_code, cfg->code_size);
100 #elif defined(__native_client_codegen__)
101         guint old_padding;
102         gpointer native_code;
103         guint alignment_check;
104
105         /* Save the old alignment offset so we can re-align after the realloc. */
106         old_padding = (guint)(cfg->native_code - cfg->native_code_alloc);
107         cfg->code_size = NACL_BUNDLE_ALIGN_UP (cfg->code_size);
108
109         cfg->native_code_alloc = g_realloc ( cfg->native_code_alloc,
110                                                                                  cfg->code_size + kNaClAlignment );
111
112         /* Align native_code to next nearest kNaClAlignment byte. */
113         native_code = (guint)cfg->native_code_alloc + kNaClAlignment;
114         native_code = (guint)native_code & ~kNaClAlignmentMask;
115
116         /* Shift the data to be 32-byte aligned again. */
117         memmove (native_code, cfg->native_code_alloc + old_padding, cfg->code_size);
118
119         alignment_check = (guint)native_code & kNaClAlignmentMask;
120         g_assert (alignment_check == 0);
121         return native_code;
122 #else
123         g_assert_not_reached ();
124         return cfg->native_code;
125 #endif
126 }
127
128 #ifdef __native_client_codegen__
129
130 /* Prevent instructions from straddling a 32-byte alignment boundary.   */
131 /* Instructions longer than 32 bytes must be aligned internally.        */
132 /* IN: pcode, instlen                                                   */
133 /* OUT: pcode                                                           */
134 void mono_nacl_align_inst(guint8 **pcode, int instlen) {
135   int space_in_block;
136
137   space_in_block = kNaClAlignment - ((uintptr_t)(*pcode) & kNaClAlignmentMask);
138
139   if (G_UNLIKELY (instlen >= kNaClAlignment)) {
140     g_assert_not_reached();
141   } else if (instlen > space_in_block) {
142     *pcode = mono_arch_nacl_pad(*pcode, space_in_block);
143   }
144 }
145
146 /* Move emitted call sequence to the end of a kNaClAlignment-byte block.  */
147 /* IN: start    pointer to start of call sequence                         */
148 /* IN: pcode    pointer to end of call sequence (current "IP")            */
149 /* OUT: start   pointer to the start of the call sequence after padding   */
150 /* OUT: pcode   pointer to the end of the call sequence after padding     */
151 void mono_nacl_align_call(guint8 **start, guint8 **pcode) {
152   const size_t MAX_NACL_CALL_LENGTH = kNaClAlignment;
153   guint8 copy_of_call[MAX_NACL_CALL_LENGTH];
154   guint8 *temp;
155
156   const size_t length = (size_t)((*pcode)-(*start));
157   g_assert(length < MAX_NACL_CALL_LENGTH);
158
159   memcpy(copy_of_call, *start, length);
160   temp = mono_nacl_pad_call(*start, (guint8)length);
161   memcpy(temp, copy_of_call, length);
162   (*start) = temp;
163   (*pcode) = temp + length;
164 }
165
166 /* mono_nacl_pad_call(): Insert padding for Native Client call instructions */
167 /*    code     pointer to buffer for emitting code                          */
168 /*    ilength  length of call instruction                                   */
169 guint8 *mono_nacl_pad_call(guint8 *code, guint8 ilength) {
170   int freeSpaceInBlock = kNaClAlignment - ((uintptr_t)code & kNaClAlignmentMask);
171   int padding = freeSpaceInBlock - ilength;
172
173   if (padding < 0) {
174     /* There isn't enough space in this block for the instruction. */
175     /* Fill this block and start a new one.                        */
176     code = mono_arch_nacl_pad(code, freeSpaceInBlock);
177     freeSpaceInBlock = kNaClAlignment;
178     padding = freeSpaceInBlock - ilength;
179   }
180   g_assert(ilength > 0);
181   g_assert(padding >= 0);
182   g_assert(padding < kNaClAlignment);
183   if (0 == padding) return code;
184   return mono_arch_nacl_pad(code, padding);
185 }
186
187 guint8 *mono_nacl_align(guint8 *code) {
188   int padding = kNaClAlignment - ((uintptr_t)code & kNaClAlignmentMask);
189   if (padding != kNaClAlignment) code = mono_arch_nacl_pad(code, padding);
190   return code;
191 }
192
193 void mono_nacl_fix_patches(const guint8 *code, MonoJumpInfo *ji)
194 {
195   MonoJumpInfo *patch_info;
196   for (patch_info = ji; patch_info; patch_info = patch_info->next) {
197     unsigned char *ip = patch_info->ip.i + code;
198     ip = mono_arch_nacl_skip_nops(ip);
199     patch_info->ip.i = ip - code;
200   }
201 }
202 #endif  /* __native_client_codegen__ */
203
204 typedef struct {
205         MonoExceptionClause *clause;
206         MonoBasicBlock *basic_block;
207         int start_offset;
208 } TryBlockHole;
209
210 /**
211  * mono_emit_unwind_op:
212  *
213  *   Add an unwind op with the given parameters for the list of unwind ops stored in
214  * cfg->unwind_ops.
215  */
216 void
217 mono_emit_unwind_op (MonoCompile *cfg, int when, int tag, int reg, int val)
218 {
219         MonoUnwindOp *op = (MonoUnwindOp *)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoUnwindOp));
220
221         op->op = tag;
222         op->reg = reg;
223         op->val = val;
224         op->when = when;
225         
226         cfg->unwind_ops = g_slist_append_mempool (cfg->mempool, cfg->unwind_ops, op);
227         if (cfg->verbose_level > 1) {
228                 switch (tag) {
229                 case DW_CFA_def_cfa:
230                         printf ("CFA: [%x] def_cfa: %s+0x%x\n", when, mono_arch_regname (reg), val);
231                         break;
232                 case DW_CFA_def_cfa_register:
233                         printf ("CFA: [%x] def_cfa_reg: %s\n", when, mono_arch_regname (reg));
234                         break;
235                 case DW_CFA_def_cfa_offset:
236                         printf ("CFA: [%x] def_cfa_offset: 0x%x\n", when, val);
237                         break;
238                 case DW_CFA_offset:
239                         printf ("CFA: [%x] offset: %s at cfa-0x%x\n", when, mono_arch_regname (reg), -val);
240                         break;
241                 }
242         }
243 }
244
245 #define MONO_INIT_VARINFO(vi,id) do { \
246         (vi)->range.first_use.pos.bid = 0xffff; \
247         (vi)->reg = -1; \
248         (vi)->idx = (id); \
249 } while (0)
250
251 /**
252  * mono_unlink_bblock:
253  *
254  *   Unlink two basic blocks.
255  */
256 void
257 mono_unlink_bblock (MonoCompile *cfg, MonoBasicBlock *from, MonoBasicBlock* to)
258 {
259         int i, pos;
260         gboolean found;
261
262         found = FALSE;
263         for (i = 0; i < from->out_count; ++i) {
264                 if (to == from->out_bb [i]) {
265                         found = TRUE;
266                         break;
267                 }
268         }
269         if (found) {
270                 pos = 0;
271                 for (i = 0; i < from->out_count; ++i) {
272                         if (from->out_bb [i] != to)
273                                 from->out_bb [pos ++] = from->out_bb [i];
274                 }
275                 g_assert (pos == from->out_count - 1);
276                 from->out_count--;
277         }
278
279         found = FALSE;
280         for (i = 0; i < to->in_count; ++i) {
281                 if (from == to->in_bb [i]) {
282                         found = TRUE;
283                         break;
284                 }
285         }
286         if (found) {
287                 pos = 0;
288                 for (i = 0; i < to->in_count; ++i) {
289                         if (to->in_bb [i] != from)
290                                 to->in_bb [pos ++] = to->in_bb [i];
291                 }
292                 g_assert (pos == to->in_count - 1);
293                 to->in_count--;
294         }
295 }
296
297 /*
298  * mono_bblocks_linked:
299  *
300  *   Return whenever BB1 and BB2 are linked in the CFG.
301  */
302 gboolean
303 mono_bblocks_linked (MonoBasicBlock *bb1, MonoBasicBlock *bb2)
304 {
305         int i;
306
307         for (i = 0; i < bb1->out_count; ++i) {
308                 if (bb1->out_bb [i] == bb2)
309                         return TRUE;
310         }
311
312         return FALSE;
313 }
314
315 static int
316 mono_find_block_region_notry (MonoCompile *cfg, int offset)
317 {
318         MonoMethodHeader *header = cfg->header;
319         MonoExceptionClause *clause;
320         int i;
321
322         for (i = 0; i < header->num_clauses; ++i) {
323                 clause = &header->clauses [i];
324                 if ((clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) && (offset >= clause->data.filter_offset) &&
325                     (offset < (clause->handler_offset)))
326                         return ((i + 1) << 8) | MONO_REGION_FILTER | clause->flags;
327                            
328                 if (MONO_OFFSET_IN_HANDLER (clause, offset)) {
329                         if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY)
330                                 return ((i + 1) << 8) | MONO_REGION_FINALLY | clause->flags;
331                         else if (clause->flags == MONO_EXCEPTION_CLAUSE_FAULT)
332                                 return ((i + 1) << 8) | MONO_REGION_FAULT | clause->flags;
333                         else
334                                 return ((i + 1) << 8) | MONO_REGION_CATCH | clause->flags;
335                 }
336         }
337
338         return -1;
339 }
340
341 /*
342  * mono_get_block_region_notry:
343  *
344  *   Return the region corresponding to REGION, ignoring try clauses nested inside
345  * finally clauses.
346  */
347 int
348 mono_get_block_region_notry (MonoCompile *cfg, int region)
349 {
350         if ((region & (0xf << 4)) == MONO_REGION_TRY) {
351                 MonoMethodHeader *header = cfg->header;
352                 
353                 /*
354                  * This can happen if a try clause is nested inside a finally clause.
355                  */
356                 int clause_index = (region >> 8) - 1;
357                 g_assert (clause_index >= 0 && clause_index < header->num_clauses);
358                 
359                 region = mono_find_block_region_notry (cfg, header->clauses [clause_index].try_offset);
360         }
361
362         return region;
363 }
364
365 MonoInst *
366 mono_find_spvar_for_region (MonoCompile *cfg, int region)
367 {
368         region = mono_get_block_region_notry (cfg, region);
369
370         return (MonoInst *)g_hash_table_lookup (cfg->spvars, GINT_TO_POINTER (region));
371 }
372
373 static void
374 df_visit (MonoBasicBlock *start, int *dfn, MonoBasicBlock **array)
375 {
376         int i;
377
378         array [*dfn] = start;
379         /* g_print ("visit %d at %p (BB%ld)\n", *dfn, start->cil_code, start->block_num); */
380         for (i = 0; i < start->out_count; ++i) {
381                 if (start->out_bb [i]->dfn)
382                         continue;
383                 (*dfn)++;
384                 start->out_bb [i]->dfn = *dfn;
385                 start->out_bb [i]->df_parent = start;
386                 array [*dfn] = start->out_bb [i];
387                 df_visit (start->out_bb [i], dfn, array);
388         }
389 }
390
391 guint32
392 mono_reverse_branch_op (guint32 opcode)
393 {
394         static const int reverse_map [] = {
395                 CEE_BNE_UN, CEE_BLT, CEE_BLE, CEE_BGT, CEE_BGE,
396                 CEE_BEQ, CEE_BLT_UN, CEE_BLE_UN, CEE_BGT_UN, CEE_BGE_UN
397         };
398         static const int reverse_fmap [] = {
399                 OP_FBNE_UN, OP_FBLT, OP_FBLE, OP_FBGT, OP_FBGE,
400                 OP_FBEQ, OP_FBLT_UN, OP_FBLE_UN, OP_FBGT_UN, OP_FBGE_UN
401         };
402         static const int reverse_lmap [] = {
403                 OP_LBNE_UN, OP_LBLT, OP_LBLE, OP_LBGT, OP_LBGE,
404                 OP_LBEQ, OP_LBLT_UN, OP_LBLE_UN, OP_LBGT_UN, OP_LBGE_UN
405         };
406         static const int reverse_imap [] = {
407                 OP_IBNE_UN, OP_IBLT, OP_IBLE, OP_IBGT, OP_IBGE,
408                 OP_IBEQ, OP_IBLT_UN, OP_IBLE_UN, OP_IBGT_UN, OP_IBGE_UN
409         };
410                                 
411         if (opcode >= CEE_BEQ && opcode <= CEE_BLT_UN) {
412                 opcode = reverse_map [opcode - CEE_BEQ];
413         } else if (opcode >= OP_FBEQ && opcode <= OP_FBLT_UN) {
414                 opcode = reverse_fmap [opcode - OP_FBEQ];
415         } else if (opcode >= OP_LBEQ && opcode <= OP_LBLT_UN) {
416                 opcode = reverse_lmap [opcode - OP_LBEQ];
417         } else if (opcode >= OP_IBEQ && opcode <= OP_IBLT_UN) {
418                 opcode = reverse_imap [opcode - OP_IBEQ];
419         } else
420                 g_assert_not_reached ();
421
422         return opcode;
423 }
424
425 guint
426 mono_type_to_store_membase (MonoCompile *cfg, MonoType *type)
427 {
428         type = mini_get_underlying_type (type);
429
430 handle_enum:
431         switch (type->type) {
432         case MONO_TYPE_I1:
433         case MONO_TYPE_U1:
434                 return OP_STOREI1_MEMBASE_REG;
435         case MONO_TYPE_I2:
436         case MONO_TYPE_U2:
437                 return OP_STOREI2_MEMBASE_REG;
438         case MONO_TYPE_I4:
439         case MONO_TYPE_U4:
440                 return OP_STOREI4_MEMBASE_REG;
441         case MONO_TYPE_I:
442         case MONO_TYPE_U:
443         case MONO_TYPE_PTR:
444         case MONO_TYPE_FNPTR:
445                 return OP_STORE_MEMBASE_REG;
446         case MONO_TYPE_CLASS:
447         case MONO_TYPE_STRING:
448         case MONO_TYPE_OBJECT:
449         case MONO_TYPE_SZARRAY:
450         case MONO_TYPE_ARRAY:    
451                 return OP_STORE_MEMBASE_REG;
452         case MONO_TYPE_I8:
453         case MONO_TYPE_U8:
454                 return OP_STOREI8_MEMBASE_REG;
455         case MONO_TYPE_R4:
456                 return OP_STORER4_MEMBASE_REG;
457         case MONO_TYPE_R8:
458                 return OP_STORER8_MEMBASE_REG;
459         case MONO_TYPE_VALUETYPE:
460                 if (type->data.klass->enumtype) {
461                         type = mono_class_enum_basetype (type->data.klass);
462                         goto handle_enum;
463                 }
464                 if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type (type)))
465                         return OP_STOREX_MEMBASE;
466                 return OP_STOREV_MEMBASE;
467         case MONO_TYPE_TYPEDBYREF:
468                 return OP_STOREV_MEMBASE;
469         case MONO_TYPE_GENERICINST:
470                 type = &type->data.generic_class->container_class->byval_arg;
471                 goto handle_enum;
472         case MONO_TYPE_VAR:
473         case MONO_TYPE_MVAR:
474                 g_assert (mini_type_var_is_vt (type));
475                 return OP_STOREV_MEMBASE;
476         default:
477                 g_error ("unknown type 0x%02x in type_to_store_membase", type->type);
478         }
479         return -1;
480 }
481
482 guint
483 mono_type_to_load_membase (MonoCompile *cfg, MonoType *type)
484 {
485         type = mini_get_underlying_type (type);
486
487         switch (type->type) {
488         case MONO_TYPE_I1:
489                 return OP_LOADI1_MEMBASE;
490         case MONO_TYPE_U1:
491                 return OP_LOADU1_MEMBASE;
492         case MONO_TYPE_I2:
493                 return OP_LOADI2_MEMBASE;
494         case MONO_TYPE_U2:
495                 return OP_LOADU2_MEMBASE;
496         case MONO_TYPE_I4:
497                 return OP_LOADI4_MEMBASE;
498         case MONO_TYPE_U4:
499                 return OP_LOADU4_MEMBASE;
500         case MONO_TYPE_I:
501         case MONO_TYPE_U:
502         case MONO_TYPE_PTR:
503         case MONO_TYPE_FNPTR:
504                 return OP_LOAD_MEMBASE;
505         case MONO_TYPE_CLASS:
506         case MONO_TYPE_STRING:
507         case MONO_TYPE_OBJECT:
508         case MONO_TYPE_SZARRAY:
509         case MONO_TYPE_ARRAY:    
510                 return OP_LOAD_MEMBASE;
511         case MONO_TYPE_I8:
512         case MONO_TYPE_U8:
513                 return OP_LOADI8_MEMBASE;
514         case MONO_TYPE_R4:
515                 return OP_LOADR4_MEMBASE;
516         case MONO_TYPE_R8:
517                 return OP_LOADR8_MEMBASE;
518         case MONO_TYPE_VALUETYPE:
519                 if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type (type)))
520                         return OP_LOADX_MEMBASE;
521         case MONO_TYPE_TYPEDBYREF:
522                 return OP_LOADV_MEMBASE;
523         case MONO_TYPE_GENERICINST:
524                 if (mono_type_generic_inst_is_valuetype (type))
525                         return OP_LOADV_MEMBASE;
526                 else
527                         return OP_LOAD_MEMBASE;
528                 break;
529         case MONO_TYPE_VAR:
530         case MONO_TYPE_MVAR:
531                 g_assert (cfg->gshared);
532                 g_assert (mini_type_var_is_vt (type));
533                 return OP_LOADV_MEMBASE;
534         default:
535                 g_error ("unknown type 0x%02x in type_to_load_membase", type->type);
536         }
537         return -1;
538 }
539
540 guint
541 mini_type_to_stind (MonoCompile* cfg, MonoType *type)
542 {
543         type = mini_get_underlying_type (type);
544         if (cfg->gshared && !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
545                 g_assert (mini_type_var_is_vt (type));
546                 return CEE_STOBJ;
547         }
548         return mono_type_to_stind (type);
549 }
550
551 int
552 mono_op_imm_to_op (int opcode)
553 {
554         switch (opcode) {
555         case OP_ADD_IMM:
556 #if SIZEOF_REGISTER == 4
557                 return OP_IADD;
558 #else
559                 return OP_LADD;
560 #endif
561         case OP_IADD_IMM:
562                 return OP_IADD;
563         case OP_LADD_IMM:
564                 return OP_LADD;
565         case OP_ISUB_IMM:
566                 return OP_ISUB;
567         case OP_LSUB_IMM:
568                 return OP_LSUB;
569         case OP_IMUL_IMM:
570                 return OP_IMUL;
571         case OP_LMUL_IMM:
572                 return OP_LMUL;
573         case OP_AND_IMM:
574 #if SIZEOF_REGISTER == 4
575                 return OP_IAND;
576 #else
577                 return OP_LAND;
578 #endif
579         case OP_OR_IMM:
580 #if SIZEOF_REGISTER == 4
581                 return OP_IOR;
582 #else
583                 return OP_LOR;
584 #endif
585         case OP_XOR_IMM:
586 #if SIZEOF_REGISTER == 4
587                 return OP_IXOR;
588 #else
589                 return OP_LXOR;
590 #endif
591         case OP_IAND_IMM:
592                 return OP_IAND;
593         case OP_LAND_IMM:
594                 return OP_LAND;
595         case OP_IOR_IMM:
596                 return OP_IOR;
597         case OP_LOR_IMM:
598                 return OP_LOR;
599         case OP_IXOR_IMM:
600                 return OP_IXOR;
601         case OP_LXOR_IMM:
602                 return OP_LXOR;
603         case OP_ISHL_IMM:
604                 return OP_ISHL;
605         case OP_LSHL_IMM:
606                 return OP_LSHL;
607         case OP_ISHR_IMM:
608                 return OP_ISHR;
609         case OP_LSHR_IMM:
610                 return OP_LSHR;
611         case OP_ISHR_UN_IMM:
612                 return OP_ISHR_UN;
613         case OP_LSHR_UN_IMM:
614                 return OP_LSHR_UN;
615         case OP_IDIV_IMM:
616                 return OP_IDIV;
617         case OP_LDIV_IMM:
618                 return OP_LDIV;
619         case OP_IDIV_UN_IMM:
620                 return OP_IDIV_UN;
621         case OP_LDIV_UN_IMM:
622                 return OP_LDIV_UN;
623         case OP_IREM_UN_IMM:
624                 return OP_IREM_UN;
625         case OP_LREM_UN_IMM:
626                 return OP_LREM_UN;
627         case OP_IREM_IMM:
628                 return OP_IREM;
629         case OP_LREM_IMM:
630                 return OP_LREM;
631         case OP_DIV_IMM:
632 #if SIZEOF_REGISTER == 4
633                 return OP_IDIV;
634 #else
635                 return OP_LDIV;
636 #endif
637         case OP_REM_IMM:
638 #if SIZEOF_REGISTER == 4
639                 return OP_IREM;
640 #else
641                 return OP_LREM;
642 #endif
643         case OP_ADDCC_IMM:
644                 return OP_ADDCC;
645         case OP_ADC_IMM:
646                 return OP_ADC;
647         case OP_SUBCC_IMM:
648                 return OP_SUBCC;
649         case OP_SBB_IMM:
650                 return OP_SBB;
651         case OP_IADC_IMM:
652                 return OP_IADC;
653         case OP_ISBB_IMM:
654                 return OP_ISBB;
655         case OP_COMPARE_IMM:
656                 return OP_COMPARE;
657         case OP_ICOMPARE_IMM:
658                 return OP_ICOMPARE;
659         case OP_LOCALLOC_IMM:
660                 return OP_LOCALLOC;
661         }
662
663         return -1;
664 }
665
666 /*
667  * mono_decompose_op_imm:
668  *
669  *   Replace the OP_.._IMM INS with its non IMM variant.
670  */
671 void
672 mono_decompose_op_imm (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins)
673 {
674         int opcode2 = mono_op_imm_to_op (ins->opcode);
675         MonoInst *temp;
676         guint32 dreg;
677         const char *spec = INS_INFO (ins->opcode);
678
679         if (spec [MONO_INST_SRC2] == 'l') {
680                 dreg = mono_alloc_lreg (cfg);
681
682                 /* Load the 64bit constant using decomposed ops */
683                 MONO_INST_NEW (cfg, temp, OP_ICONST);
684                 temp->inst_c0 = ins->inst_ls_word;
685                 temp->dreg = MONO_LVREG_LS (dreg);
686                 mono_bblock_insert_before_ins (bb, ins, temp);
687
688                 MONO_INST_NEW (cfg, temp, OP_ICONST);
689                 temp->inst_c0 = ins->inst_ms_word;
690                 temp->dreg = MONO_LVREG_MS (dreg);
691         } else {
692                 dreg = mono_alloc_ireg (cfg);
693
694                 MONO_INST_NEW (cfg, temp, OP_ICONST);
695                 temp->inst_c0 = ins->inst_imm;
696                 temp->dreg = dreg;
697         }
698
699         mono_bblock_insert_before_ins (bb, ins, temp);
700
701         if (opcode2 == -1)
702                 g_error ("mono_op_imm_to_op failed for %s\n", mono_inst_name (ins->opcode));
703         ins->opcode = opcode2;
704
705         if (ins->opcode == OP_LOCALLOC)
706                 ins->sreg1 = dreg;
707         else
708                 ins->sreg2 = dreg;
709
710         bb->max_vreg = MAX (bb->max_vreg, cfg->next_vreg);
711 }
712
713 static void
714 set_vreg_to_inst (MonoCompile *cfg, int vreg, MonoInst *inst)
715 {
716         if (vreg >= cfg->vreg_to_inst_len) {
717                 MonoInst **tmp = cfg->vreg_to_inst;
718                 int size = cfg->vreg_to_inst_len;
719
720                 while (vreg >= cfg->vreg_to_inst_len)
721                         cfg->vreg_to_inst_len = cfg->vreg_to_inst_len ? cfg->vreg_to_inst_len * 2 : 32;
722                 cfg->vreg_to_inst = (MonoInst **)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst*) * cfg->vreg_to_inst_len);
723                 if (size)
724                         memcpy (cfg->vreg_to_inst, tmp, size * sizeof (MonoInst*));
725         }
726         cfg->vreg_to_inst [vreg] = inst;
727 }
728
729 #define mono_type_is_long(type) (!(type)->byref && ((mono_type_get_underlying_type (type)->type == MONO_TYPE_I8) || (mono_type_get_underlying_type (type)->type == MONO_TYPE_U8)))
730 #define mono_type_is_float(type) (!(type)->byref && (((type)->type == MONO_TYPE_R8) || ((type)->type == MONO_TYPE_R4)))
731
732 MonoInst*
733 mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode, int vreg)
734 {
735         MonoInst *inst;
736         int num = cfg->num_varinfo;
737         gboolean regpair;
738
739         type = mini_get_underlying_type (type);
740
741         if ((num + 1) >= cfg->varinfo_count) {
742                 int orig_count = cfg->varinfo_count;
743                 cfg->varinfo_count = cfg->varinfo_count ? (cfg->varinfo_count * 2) : 32;
744                 cfg->varinfo = (MonoInst **)g_realloc (cfg->varinfo, sizeof (MonoInst*) * cfg->varinfo_count);
745                 cfg->vars = (MonoMethodVar *)g_realloc (cfg->vars, sizeof (MonoMethodVar) * cfg->varinfo_count);
746                 memset (&cfg->vars [orig_count], 0, (cfg->varinfo_count - orig_count) * sizeof (MonoMethodVar));
747         }
748
749         cfg->stat_allocate_var++;
750
751         MONO_INST_NEW (cfg, inst, opcode);
752         inst->inst_c0 = num;
753         inst->inst_vtype = type;
754         inst->klass = mono_class_from_mono_type (type);
755         type_to_eval_stack_type (cfg, type, inst);
756         /* if set to 1 the variable is native */
757         inst->backend.is_pinvoke = 0;
758         inst->dreg = vreg;
759
760         if (mono_class_has_failure (inst->klass))
761                 mono_cfg_set_exception (cfg, MONO_EXCEPTION_TYPE_LOAD);
762
763         if (cfg->compute_gc_maps) {
764                 if (type->byref) {
765                         mono_mark_vreg_as_mp (cfg, vreg);
766                 } else {
767                         if ((MONO_TYPE_ISSTRUCT (type) && inst->klass->has_references) || mini_type_is_reference (type)) {
768                                 inst->flags |= MONO_INST_GC_TRACK;
769                                 mono_mark_vreg_as_ref (cfg, vreg);
770                         }
771                 }
772         }
773         
774         cfg->varinfo [num] = inst;
775
776         MONO_INIT_VARINFO (&cfg->vars [num], num);
777         MONO_VARINFO (cfg, num)->vreg = vreg;
778
779         if (vreg != -1)
780                 set_vreg_to_inst (cfg, vreg, inst);
781
782 #if SIZEOF_REGISTER == 4
783         if (mono_arch_is_soft_float ()) {
784                 regpair = mono_type_is_long (type) || mono_type_is_float (type);
785         } else {
786                 regpair = mono_type_is_long (type);
787         }
788 #else
789         regpair = FALSE;
790 #endif
791
792         if (regpair) {
793                 MonoInst *tree;
794
795                 /* 
796                  * These two cannot be allocated using create_var_for_vreg since that would
797                  * put it into the cfg->varinfo array, confusing many parts of the JIT.
798                  */
799
800                 /* 
801                  * Set flags to VOLATILE so SSA skips it.
802                  */
803
804                 if (cfg->verbose_level >= 4) {
805                         printf ("  Create LVAR R%d (R%d, R%d)\n", inst->dreg, MONO_LVREG_LS (inst->dreg), MONO_LVREG_MS (inst->dreg));
806                 }
807
808                 if (mono_arch_is_soft_float () && cfg->opt & MONO_OPT_SSA) {
809                         if (mono_type_is_float (type))
810                                 inst->flags = MONO_INST_VOLATILE;
811                 }
812
813                 /* Allocate a dummy MonoInst for the first vreg */
814                 MONO_INST_NEW (cfg, tree, OP_LOCAL);
815                 tree->dreg = MONO_LVREG_LS (inst->dreg);
816                 if (cfg->opt & MONO_OPT_SSA)
817                         tree->flags = MONO_INST_VOLATILE;
818                 tree->inst_c0 = num;
819                 tree->type = STACK_I4;
820                 tree->inst_vtype = &mono_defaults.int32_class->byval_arg;
821                 tree->klass = mono_class_from_mono_type (tree->inst_vtype);
822
823                 set_vreg_to_inst (cfg, MONO_LVREG_LS (inst->dreg), tree);
824
825                 /* Allocate a dummy MonoInst for the second vreg */
826                 MONO_INST_NEW (cfg, tree, OP_LOCAL);
827                 tree->dreg = MONO_LVREG_MS (inst->dreg);
828                 if (cfg->opt & MONO_OPT_SSA)
829                         tree->flags = MONO_INST_VOLATILE;
830                 tree->inst_c0 = num;
831                 tree->type = STACK_I4;
832                 tree->inst_vtype = &mono_defaults.int32_class->byval_arg;
833                 tree->klass = mono_class_from_mono_type (tree->inst_vtype);
834
835                 set_vreg_to_inst (cfg, MONO_LVREG_MS (inst->dreg), tree);
836         }
837
838         cfg->num_varinfo++;
839         if (cfg->verbose_level > 2)
840                 g_print ("created temp %d (R%d) of type %s\n", num, vreg, mono_type_get_name (type));
841         return inst;
842 }
843
844 MonoInst*
845 mono_compile_create_var (MonoCompile *cfg, MonoType *type, int opcode)
846 {
847         int dreg;
848         type = mini_get_underlying_type (type);
849
850         if (mono_type_is_long (type))
851                 dreg = mono_alloc_dreg (cfg, STACK_I8);
852         else if (mono_arch_is_soft_float () && mono_type_is_float (type))
853                 dreg = mono_alloc_dreg (cfg, STACK_R8);
854         else
855                 /* All the others are unified */
856                 dreg = mono_alloc_preg (cfg);
857
858         return mono_compile_create_var_for_vreg (cfg, type, opcode, dreg);
859 }
860
861 MonoInst*
862 mini_get_int_to_float_spill_area (MonoCompile *cfg)
863 {
864 #ifdef TARGET_X86
865         if (!cfg->iconv_raw_var) {
866                 cfg->iconv_raw_var = mono_compile_create_var (cfg, &mono_defaults.int32_class->byval_arg, OP_LOCAL);
867                 cfg->iconv_raw_var->flags |= MONO_INST_VOLATILE; /*FIXME, use the don't regalloc flag*/
868         }
869         return cfg->iconv_raw_var;
870 #else
871         return NULL;
872 #endif
873 }
874
875 void
876 mono_mark_vreg_as_ref (MonoCompile *cfg, int vreg)
877 {
878         if (vreg >= cfg->vreg_is_ref_len) {
879                 gboolean *tmp = cfg->vreg_is_ref;
880                 int size = cfg->vreg_is_ref_len;
881
882                 while (vreg >= cfg->vreg_is_ref_len)
883                         cfg->vreg_is_ref_len = cfg->vreg_is_ref_len ? cfg->vreg_is_ref_len * 2 : 32;
884                 cfg->vreg_is_ref = (gboolean *)mono_mempool_alloc0 (cfg->mempool, sizeof (gboolean) * cfg->vreg_is_ref_len);
885                 if (size)
886                         memcpy (cfg->vreg_is_ref, tmp, size * sizeof (gboolean));
887         }
888         cfg->vreg_is_ref [vreg] = TRUE;
889 }       
890
891 void
892 mono_mark_vreg_as_mp (MonoCompile *cfg, int vreg)
893 {
894         if (vreg >= cfg->vreg_is_mp_len) {
895                 gboolean *tmp = cfg->vreg_is_mp;
896                 int size = cfg->vreg_is_mp_len;
897
898                 while (vreg >= cfg->vreg_is_mp_len)
899                         cfg->vreg_is_mp_len = cfg->vreg_is_mp_len ? cfg->vreg_is_mp_len * 2 : 32;
900                 cfg->vreg_is_mp = (gboolean *)mono_mempool_alloc0 (cfg->mempool, sizeof (gboolean) * cfg->vreg_is_mp_len);
901                 if (size)
902                         memcpy (cfg->vreg_is_mp, tmp, size * sizeof (gboolean));
903         }
904         cfg->vreg_is_mp [vreg] = TRUE;
905 }       
906
907 static MonoType*
908 type_from_stack_type (MonoInst *ins)
909 {
910         switch (ins->type) {
911         case STACK_I4: return &mono_defaults.int32_class->byval_arg;
912         case STACK_I8: return &mono_defaults.int64_class->byval_arg;
913         case STACK_PTR: return &mono_defaults.int_class->byval_arg;
914         case STACK_R8: return &mono_defaults.double_class->byval_arg;
915         case STACK_MP:
916                 /* 
917                  * this if used to be commented without any specific reason, but
918                  * it breaks #80235 when commented
919                  */
920                 if (ins->klass)
921                         return &ins->klass->this_arg;
922                 else
923                         return &mono_defaults.object_class->this_arg;
924         case STACK_OBJ:
925                 /* ins->klass may not be set for ldnull.
926                  * Also, if we have a boxed valuetype, we want an object lass,
927                  * not the valuetype class
928                  */
929                 if (ins->klass && !ins->klass->valuetype)
930                         return &ins->klass->byval_arg;
931                 return &mono_defaults.object_class->byval_arg;
932         case STACK_VTYPE: return &ins->klass->byval_arg;
933         default:
934                 g_error ("stack type %d to montype not handled\n", ins->type);
935         }
936         return NULL;
937 }
938
939 MonoType*
940 mono_type_from_stack_type (MonoInst *ins)
941 {
942         return type_from_stack_type (ins);
943 }
944
945 /*
946  * mono_add_ins_to_end:
947  *
948  *   Same as MONO_ADD_INS, but add INST before any branches at the end of BB.
949  */
950 void
951 mono_add_ins_to_end (MonoBasicBlock *bb, MonoInst *inst)
952 {
953         int opcode;
954
955         if (!bb->code) {
956                 MONO_ADD_INS (bb, inst);
957                 return;
958         }
959
960         switch (bb->last_ins->opcode) {
961         case OP_BR:
962         case OP_BR_REG:
963         case CEE_BEQ:
964         case CEE_BGE:
965         case CEE_BGT:
966         case CEE_BLE:
967         case CEE_BLT:
968         case CEE_BNE_UN:
969         case CEE_BGE_UN:
970         case CEE_BGT_UN:
971         case CEE_BLE_UN:
972         case CEE_BLT_UN:
973         case OP_SWITCH:
974                 mono_bblock_insert_before_ins (bb, bb->last_ins, inst);
975                 break;
976         default:
977                 if (MONO_IS_COND_BRANCH_OP (bb->last_ins)) {
978                         /* Need to insert the ins before the compare */
979                         if (bb->code == bb->last_ins) {
980                                 mono_bblock_insert_before_ins (bb, bb->last_ins, inst);
981                                 return;
982                         }
983
984                         if (bb->code->next == bb->last_ins) {
985                                 /* Only two instructions */
986                                 opcode = bb->code->opcode;
987
988                                 if ((opcode == OP_COMPARE) || (opcode == OP_COMPARE_IMM) || (opcode == OP_ICOMPARE) || (opcode == OP_ICOMPARE_IMM) || (opcode == OP_FCOMPARE) || (opcode == OP_LCOMPARE) || (opcode == OP_LCOMPARE_IMM) || (opcode == OP_RCOMPARE)) {
989                                         /* NEW IR */
990                                         mono_bblock_insert_before_ins (bb, bb->code, inst);
991                                 } else {
992                                         mono_bblock_insert_before_ins (bb, bb->last_ins, inst);
993                                 }
994                         } else {
995                                 opcode = bb->last_ins->prev->opcode;
996
997                                 if ((opcode == OP_COMPARE) || (opcode == OP_COMPARE_IMM) || (opcode == OP_ICOMPARE) || (opcode == OP_ICOMPARE_IMM) || (opcode == OP_FCOMPARE) || (opcode == OP_LCOMPARE) || (opcode == OP_LCOMPARE_IMM) || (opcode == OP_RCOMPARE)) {
998                                         /* NEW IR */
999                                         mono_bblock_insert_before_ins (bb, bb->last_ins->prev, inst);
1000                                 } else {
1001                                         mono_bblock_insert_before_ins (bb, bb->last_ins, inst);
1002                                 }                                       
1003                         }
1004                 }
1005                 else
1006                         MONO_ADD_INS (bb, inst);
1007                 break;
1008         }
1009 }
1010
1011 void
1012 mono_create_jump_table (MonoCompile *cfg, MonoInst *label, MonoBasicBlock **bbs, int num_blocks)
1013 {
1014         MonoJumpInfo *ji = (MonoJumpInfo *)mono_mempool_alloc (cfg->mempool, sizeof (MonoJumpInfo));
1015         MonoJumpInfoBBTable *table;
1016
1017         table = (MonoJumpInfoBBTable *)mono_mempool_alloc (cfg->mempool, sizeof (MonoJumpInfoBBTable));
1018         table->table = bbs;
1019         table->table_size = num_blocks;
1020         
1021         ji->ip.label = label;
1022         ji->type = MONO_PATCH_INFO_SWITCH;
1023         ji->data.table = table;
1024         ji->next = cfg->patch_info;
1025         cfg->patch_info = ji;
1026 }
1027
1028 static MonoMethodSignature *
1029 mono_get_array_new_va_signature (int arity)
1030 {
1031         static GHashTable *sighash;
1032         MonoMethodSignature *res;
1033         int i;
1034
1035         mono_jit_lock ();
1036         if (!sighash) {
1037                 sighash = g_hash_table_new (NULL, NULL);
1038         }
1039         else if ((res = (MonoMethodSignature *)g_hash_table_lookup (sighash, GINT_TO_POINTER (arity)))) {
1040                 mono_jit_unlock ();
1041                 return res;
1042         }
1043
1044         res = mono_metadata_signature_alloc (mono_defaults.corlib, arity + 1);
1045
1046         res->pinvoke = 1;
1047         if (ARCH_VARARG_ICALLS)
1048                 /* Only set this only some archs since not all backends can handle varargs+pinvoke */
1049                 res->call_convention = MONO_CALL_VARARG;
1050
1051 #ifdef TARGET_WIN32
1052         res->call_convention = MONO_CALL_C;
1053 #endif
1054
1055         res->params [0] = &mono_defaults.int_class->byval_arg;  
1056         for (i = 0; i < arity; i++)
1057                 res->params [i + 1] = &mono_defaults.int_class->byval_arg;
1058
1059         res->ret = &mono_defaults.object_class->byval_arg;
1060
1061         g_hash_table_insert (sighash, GINT_TO_POINTER (arity), res);
1062         mono_jit_unlock ();
1063
1064         return res;
1065 }
1066
1067 MonoJitICallInfo *
1068 mono_get_array_new_va_icall (int rank)
1069 {
1070         MonoMethodSignature *esig;
1071         char icall_name [256];
1072         char *name;
1073         MonoJitICallInfo *info;
1074
1075         /* Need to register the icall so it gets an icall wrapper */
1076         sprintf (icall_name, "ves_array_new_va_%d", rank);
1077
1078         mono_jit_lock ();
1079         info = mono_find_jit_icall_by_name (icall_name);
1080         if (info == NULL) {
1081                 esig = mono_get_array_new_va_signature (rank);
1082                 name = g_strdup (icall_name);
1083                 info = mono_register_jit_icall (mono_array_new_va, name, esig, FALSE);
1084         }
1085         mono_jit_unlock ();
1086
1087         return info;
1088 }
1089
1090 gboolean
1091 mini_class_is_system_array (MonoClass *klass)
1092 {
1093         if (klass->parent == mono_defaults.array_class)
1094                 return TRUE;
1095         else
1096                 return FALSE;
1097 }
1098
1099 gboolean
1100 mini_assembly_can_skip_verification (MonoDomain *domain, MonoMethod *method)
1101 {
1102         MonoAssembly *assembly = method->klass->image->assembly;
1103         if (method->wrapper_type != MONO_WRAPPER_NONE && method->wrapper_type != MONO_WRAPPER_DYNAMIC_METHOD)
1104                 return FALSE;
1105         if (assembly->in_gac || assembly->image == mono_defaults.corlib)
1106                 return FALSE;
1107         return mono_assembly_has_skip_verification (assembly);
1108 }
1109
1110 /*
1111  * mini_method_verify:
1112  * 
1113  * Verify the method using the verfier.
1114  * 
1115  * Returns true if the method is invalid. 
1116  */
1117 static gboolean
1118 mini_method_verify (MonoCompile *cfg, MonoMethod *method, gboolean fail_compile)
1119 {
1120         GSList *tmp, *res;
1121         gboolean is_fulltrust;
1122
1123         if (method->verification_success)
1124                 return FALSE;
1125
1126         if (!mono_verifier_is_enabled_for_method (method))
1127                 return FALSE;
1128
1129         /*skip verification implies the assembly must be */
1130         is_fulltrust = mono_verifier_is_method_full_trust (method) ||  mini_assembly_can_skip_verification (cfg->domain, method);
1131
1132         res = mono_method_verify_with_current_settings (method, cfg->skip_visibility, is_fulltrust);
1133
1134         if (res) { 
1135                 for (tmp = res; tmp; tmp = tmp->next) {
1136                         MonoVerifyInfoExtended *info = (MonoVerifyInfoExtended *)tmp->data;
1137                         if (info->info.status == MONO_VERIFY_ERROR) {
1138                                 if (fail_compile) {
1139                                 char *method_name = mono_method_full_name (method, TRUE);
1140                                         cfg->exception_type = info->exception_type;
1141                                         cfg->exception_message = g_strdup_printf ("Error verifying %s: %s", method_name, info->info.message);
1142                                         g_free (method_name);
1143                                 }
1144                                 mono_free_verify_list (res);
1145                                 return TRUE;
1146                         }
1147                         if (info->info.status == MONO_VERIFY_NOT_VERIFIABLE && (!is_fulltrust || info->exception_type == MONO_EXCEPTION_METHOD_ACCESS || info->exception_type == MONO_EXCEPTION_FIELD_ACCESS)) {
1148                                 if (fail_compile) {
1149                                         char *method_name = mono_method_full_name (method, TRUE);
1150                                         char *msg = g_strdup_printf ("Error verifying %s: %s", method_name, info->info.message);
1151
1152                                         if (info->exception_type == MONO_EXCEPTION_METHOD_ACCESS)
1153                                                 mono_error_set_generic_error (&cfg->error, "System", "MethodAccessException", "%s", msg);
1154                                         else if (info->exception_type == MONO_EXCEPTION_FIELD_ACCESS)
1155                                                 mono_error_set_generic_error (&cfg->error, "System", "FieldAccessException", "%s", msg);
1156                                         else if (info->exception_type == MONO_EXCEPTION_UNVERIFIABLE_IL)
1157                                                 mono_error_set_generic_error (&cfg->error, "System.Security", "VerificationException", msg);
1158                                         if (!mono_error_ok (&cfg->error)) {
1159                                                 mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
1160                                                 g_free (msg);
1161                                         } else {
1162                                                 cfg->exception_type = info->exception_type;
1163                                                 cfg->exception_message = msg;
1164                                         }
1165                                         g_free (method_name);
1166                                 }
1167                                 mono_free_verify_list (res);
1168                                 return TRUE;
1169                         }
1170                 }
1171                 mono_free_verify_list (res);
1172         }
1173         method->verification_success = 1;
1174         return FALSE;
1175 }
1176
1177 /*Returns true if something went wrong*/
1178 gboolean
1179 mono_compile_is_broken (MonoCompile *cfg, MonoMethod *method, gboolean fail_compile)
1180 {
1181         MonoMethod *method_definition = method;
1182         gboolean dont_verify = method->klass->image->assembly->corlib_internal;
1183
1184         while (method_definition->is_inflated) {
1185                 MonoMethodInflated *imethod = (MonoMethodInflated *) method_definition;
1186                 method_definition = imethod->declaring;
1187         }
1188
1189         return !dont_verify && mini_method_verify (cfg, method_definition, fail_compile);
1190 }
1191
1192 static void
1193 mono_dynamic_code_hash_insert (MonoDomain *domain, MonoMethod *method, MonoJitDynamicMethodInfo *ji)
1194 {
1195         if (!domain_jit_info (domain)->dynamic_code_hash)
1196                 domain_jit_info (domain)->dynamic_code_hash = g_hash_table_new (NULL, NULL);
1197         g_hash_table_insert (domain_jit_info (domain)->dynamic_code_hash, method, ji);
1198 }
1199
1200 static MonoJitDynamicMethodInfo*
1201 mono_dynamic_code_hash_lookup (MonoDomain *domain, MonoMethod *method)
1202 {
1203         MonoJitDynamicMethodInfo *res;
1204
1205         if (domain_jit_info (domain)->dynamic_code_hash)
1206                 res = (MonoJitDynamicMethodInfo *)g_hash_table_lookup (domain_jit_info (domain)->dynamic_code_hash, method);
1207         else
1208                 res = NULL;
1209         return res;
1210 }
1211
1212 typedef struct {
1213         MonoClass *vtype;
1214         GList *active, *inactive;
1215         GSList *slots;
1216 } StackSlotInfo;
1217
1218 static gint 
1219 compare_by_interval_start_pos_func (gconstpointer a, gconstpointer b)
1220 {
1221         MonoMethodVar *v1 = (MonoMethodVar*)a;
1222         MonoMethodVar *v2 = (MonoMethodVar*)b;
1223
1224         if (v1 == v2)
1225                 return 0;
1226         else if (v1->interval->range && v2->interval->range)
1227                 return v1->interval->range->from - v2->interval->range->from;
1228         else if (v1->interval->range)
1229                 return -1;
1230         else
1231                 return 1;
1232 }
1233
1234 #if 0
1235 #define LSCAN_DEBUG(a) do { a; } while (0)
1236 #else
1237 #define LSCAN_DEBUG(a)
1238 #endif
1239
1240 static gint32*
1241 mono_allocate_stack_slots2 (MonoCompile *cfg, gboolean backward, guint32 *stack_size, guint32 *stack_align)
1242 {
1243         int i, slot, offset, size;
1244         guint32 align;
1245         MonoMethodVar *vmv;
1246         MonoInst *inst;
1247         gint32 *offsets;
1248         GList *vars = NULL, *l, *unhandled;
1249         StackSlotInfo *scalar_stack_slots, *vtype_stack_slots, *slot_info;
1250         MonoType *t;
1251         int nvtypes;
1252         gboolean reuse_slot;
1253
1254         LSCAN_DEBUG (printf ("Allocate Stack Slots 2 for %s:\n", mono_method_full_name (cfg->method, TRUE)));
1255
1256         scalar_stack_slots = (StackSlotInfo *)mono_mempool_alloc0 (cfg->mempool, sizeof (StackSlotInfo) * MONO_TYPE_PINNED);
1257         vtype_stack_slots = NULL;
1258         nvtypes = 0;
1259
1260         offsets = (gint32 *)mono_mempool_alloc (cfg->mempool, sizeof (gint32) * cfg->num_varinfo);
1261         for (i = 0; i < cfg->num_varinfo; ++i)
1262                 offsets [i] = -1;
1263
1264         for (i = cfg->locals_start; i < cfg->num_varinfo; i++) {
1265                 inst = cfg->varinfo [i];
1266                 vmv = MONO_VARINFO (cfg, i);
1267
1268                 if ((inst->flags & MONO_INST_IS_DEAD) || inst->opcode == OP_REGVAR || inst->opcode == OP_REGOFFSET)
1269                         continue;
1270
1271                 vars = g_list_prepend (vars, vmv);
1272         }
1273
1274         vars = g_list_sort (g_list_copy (vars), compare_by_interval_start_pos_func);
1275
1276         /* Sanity check */
1277         /*
1278         i = 0;
1279         for (unhandled = vars; unhandled; unhandled = unhandled->next) {
1280                 MonoMethodVar *current = unhandled->data;
1281
1282                 if (current->interval->range) {
1283                         g_assert (current->interval->range->from >= i);
1284                         i = current->interval->range->from;
1285                 }
1286         }
1287         */
1288
1289         offset = 0;
1290         *stack_align = 0;
1291         for (unhandled = vars; unhandled; unhandled = unhandled->next) {
1292                 MonoMethodVar *current = (MonoMethodVar *)unhandled->data;
1293
1294                 vmv = current;
1295                 inst = cfg->varinfo [vmv->idx];
1296
1297                 t = mono_type_get_underlying_type (inst->inst_vtype);
1298                 if (cfg->gsharedvt && mini_is_gsharedvt_variable_type (t))
1299                         continue;
1300
1301                 /* inst->backend.is_pinvoke indicates native sized value types, this is used by the
1302                 * pinvoke wrappers when they call functions returning structures */
1303                 if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (t) && t->type != MONO_TYPE_TYPEDBYREF) {
1304                         size = mono_class_native_size (mono_class_from_mono_type (t), &align);
1305                 }
1306                 else {
1307                         int ialign;
1308
1309                         size = mini_type_stack_size (t, &ialign);
1310                         align = ialign;
1311
1312                         if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type (t)))
1313                                 align = 16;
1314                 }
1315
1316                 reuse_slot = TRUE;
1317                 if (cfg->disable_reuse_stack_slots)
1318                         reuse_slot = FALSE;
1319
1320                 t = mini_get_underlying_type (t);
1321                 switch (t->type) {
1322                 case MONO_TYPE_GENERICINST:
1323                         if (!mono_type_generic_inst_is_valuetype (t)) {
1324                                 slot_info = &scalar_stack_slots [t->type];
1325                                 break;
1326                         }
1327                         /* Fall through */
1328                 case MONO_TYPE_VALUETYPE:
1329                         if (!vtype_stack_slots)
1330                                 vtype_stack_slots = (StackSlotInfo *)mono_mempool_alloc0 (cfg->mempool, sizeof (StackSlotInfo) * 256);
1331                         for (i = 0; i < nvtypes; ++i)
1332                                 if (t->data.klass == vtype_stack_slots [i].vtype)
1333                                         break;
1334                         if (i < nvtypes)
1335                                 slot_info = &vtype_stack_slots [i];
1336                         else {
1337                                 g_assert (nvtypes < 256);
1338                                 vtype_stack_slots [nvtypes].vtype = t->data.klass;
1339                                 slot_info = &vtype_stack_slots [nvtypes];
1340                                 nvtypes ++;
1341                         }
1342                         if (cfg->disable_reuse_ref_stack_slots)
1343                                 reuse_slot = FALSE;
1344                         break;
1345
1346                 case MONO_TYPE_PTR:
1347                 case MONO_TYPE_I:
1348                 case MONO_TYPE_U:
1349 #if SIZEOF_VOID_P == 4
1350                 case MONO_TYPE_I4:
1351 #else
1352                 case MONO_TYPE_I8:
1353 #endif
1354                         if (cfg->disable_ref_noref_stack_slot_share) {
1355                                 slot_info = &scalar_stack_slots [MONO_TYPE_I];
1356                                 break;
1357                         }
1358                         /* Fall through */
1359
1360                 case MONO_TYPE_CLASS:
1361                 case MONO_TYPE_OBJECT:
1362                 case MONO_TYPE_ARRAY:
1363                 case MONO_TYPE_SZARRAY:
1364                 case MONO_TYPE_STRING:
1365                         /* Share non-float stack slots of the same size */
1366                         slot_info = &scalar_stack_slots [MONO_TYPE_CLASS];
1367                         if (cfg->disable_reuse_ref_stack_slots)
1368                                 reuse_slot = FALSE;
1369                         break;
1370
1371                 default:
1372                         slot_info = &scalar_stack_slots [t->type];
1373                 }
1374
1375                 slot = 0xffffff;
1376                 if (cfg->comp_done & MONO_COMP_LIVENESS) {
1377                         int pos;
1378                         gboolean changed;
1379
1380                         //printf ("START  %2d %08x %08x\n",  vmv->idx, vmv->range.first_use.abs_pos, vmv->range.last_use.abs_pos);
1381
1382                         if (!current->interval->range) {
1383                                 if (inst->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT))
1384                                         pos = ~0;
1385                                 else {
1386                                         /* Dead */
1387                                         inst->flags |= MONO_INST_IS_DEAD;
1388                                         continue;
1389                                 }
1390                         }
1391                         else
1392                                 pos = current->interval->range->from;
1393
1394                         LSCAN_DEBUG (printf ("process R%d ", inst->dreg));
1395                         if (current->interval->range)
1396                                 LSCAN_DEBUG (mono_linterval_print (current->interval));
1397                         LSCAN_DEBUG (printf ("\n"));
1398
1399                         /* Check for intervals in active which expired or inactive */
1400                         changed = TRUE;
1401                         /* FIXME: Optimize this */
1402                         while (changed) {
1403                                 changed = FALSE;
1404                                 for (l = slot_info->active; l != NULL; l = l->next) {
1405                                         MonoMethodVar *v = (MonoMethodVar*)l->data;
1406
1407                                         if (v->interval->last_range->to < pos) {
1408                                                 slot_info->active = g_list_delete_link (slot_info->active, l);
1409                                                 slot_info->slots = g_slist_prepend_mempool (cfg->mempool, slot_info->slots, GINT_TO_POINTER (offsets [v->idx]));
1410                                                 LSCAN_DEBUG (printf ("Interval R%d has expired, adding 0x%x to slots\n", cfg->varinfo [v->idx]->dreg, offsets [v->idx]));
1411                                                 changed = TRUE;
1412                                                 break;
1413                                         }
1414                                         else if (!mono_linterval_covers (v->interval, pos)) {
1415                                                 slot_info->inactive = g_list_append (slot_info->inactive, v);
1416                                                 slot_info->active = g_list_delete_link (slot_info->active, l);
1417                                                 LSCAN_DEBUG (printf ("Interval R%d became inactive\n", cfg->varinfo [v->idx]->dreg));
1418                                                 changed = TRUE;
1419                                                 break;
1420                                         }
1421                                 }
1422                         }
1423
1424                         /* Check for intervals in inactive which expired or active */
1425                         changed = TRUE;
1426                         /* FIXME: Optimize this */
1427                         while (changed) {
1428                                 changed = FALSE;
1429                                 for (l = slot_info->inactive; l != NULL; l = l->next) {
1430                                         MonoMethodVar *v = (MonoMethodVar*)l->data;
1431
1432                                         if (v->interval->last_range->to < pos) {
1433                                                 slot_info->inactive = g_list_delete_link (slot_info->inactive, l);
1434                                                 // FIXME: Enabling this seems to cause impossible to debug crashes
1435                                                 //slot_info->slots = g_slist_prepend_mempool (cfg->mempool, slot_info->slots, GINT_TO_POINTER (offsets [v->idx]));
1436                                                 LSCAN_DEBUG (printf ("Interval R%d has expired, adding 0x%x to slots\n", cfg->varinfo [v->idx]->dreg, offsets [v->idx]));
1437                                                 changed = TRUE;
1438                                                 break;
1439                                         }
1440                                         else if (mono_linterval_covers (v->interval, pos)) {
1441                                                 slot_info->active = g_list_append (slot_info->active, v);
1442                                                 slot_info->inactive = g_list_delete_link (slot_info->inactive, l);
1443                                                 LSCAN_DEBUG (printf ("\tInterval R%d became active\n", cfg->varinfo [v->idx]->dreg));
1444                                                 changed = TRUE;
1445                                                 break;
1446                                         }
1447                                 }
1448                         }
1449
1450                         /* 
1451                          * This also handles the case when the variable is used in an
1452                          * exception region, as liveness info is not computed there.
1453                          */
1454                         /* 
1455                          * FIXME: All valuetypes are marked as INDIRECT because of LDADDR
1456                          * opcodes.
1457                          */
1458                         if (! (inst->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT))) {
1459                                 if (slot_info->slots) {
1460                                         slot = GPOINTER_TO_INT (slot_info->slots->data);
1461
1462                                         slot_info->slots = slot_info->slots->next;
1463                                 }
1464
1465                                 /* FIXME: We might want to consider the inactive intervals as well if slot_info->slots is empty */
1466
1467                                 slot_info->active = mono_varlist_insert_sorted (cfg, slot_info->active, vmv, TRUE);
1468                         }
1469                 }
1470
1471 #if 0
1472                 {
1473                         static int count = 0;
1474                         count ++;
1475
1476                         if (count == atoi (g_getenv ("COUNT3")))
1477                                 printf ("LAST: %s\n", mono_method_full_name (cfg->method, TRUE));
1478                         if (count > atoi (g_getenv ("COUNT3")))
1479                                 slot = 0xffffff;
1480                         else {
1481                                 mono_print_ins (inst);
1482                                 }
1483                 }
1484 #endif
1485
1486                 LSCAN_DEBUG (printf ("R%d %s -> 0x%x\n", inst->dreg, mono_type_full_name (t), slot));
1487
1488                 if (inst->flags & MONO_INST_LMF) {
1489                         size = sizeof (MonoLMF);
1490                         align = sizeof (mgreg_t);
1491                         reuse_slot = FALSE;
1492                 }
1493
1494                 if (!reuse_slot)
1495                         slot = 0xffffff;
1496
1497                 if (slot == 0xffffff) {
1498                         /*
1499                          * Allways allocate valuetypes to sizeof (gpointer) to allow more
1500                          * efficient copying (and to work around the fact that OP_MEMCPY
1501                          * and OP_MEMSET ignores alignment).
1502                          */
1503                         if (MONO_TYPE_ISSTRUCT (t)) {
1504                                 align = MAX (align, sizeof (gpointer));
1505                                 align = MAX (align, mono_class_min_align (mono_class_from_mono_type (t)));
1506                         }
1507
1508                         if (backward) {
1509                                 offset += size;
1510                                 offset += align - 1;
1511                                 offset &= ~(align - 1);
1512                                 slot = offset;
1513                         }
1514                         else {
1515                                 offset += align - 1;
1516                                 offset &= ~(align - 1);
1517                                 slot = offset;
1518                                 offset += size;
1519                         }
1520
1521                         if (*stack_align == 0)
1522                                 *stack_align = align;
1523                 }
1524
1525                 offsets [vmv->idx] = slot;
1526         }
1527         g_list_free (vars);
1528         for (i = 0; i < MONO_TYPE_PINNED; ++i) {
1529                 if (scalar_stack_slots [i].active)
1530                         g_list_free (scalar_stack_slots [i].active);
1531         }
1532         for (i = 0; i < nvtypes; ++i) {
1533                 if (vtype_stack_slots [i].active)
1534                         g_list_free (vtype_stack_slots [i].active);
1535         }
1536
1537         cfg->stat_locals_stack_size += offset;
1538
1539         *stack_size = offset;
1540         return offsets;
1541 }
1542
1543 /*
1544  *  mono_allocate_stack_slots:
1545  *
1546  *  Allocate stack slots for all non register allocated variables using a
1547  * linear scan algorithm.
1548  * Returns: an array of stack offsets.
1549  * STACK_SIZE is set to the amount of stack space needed.
1550  * STACK_ALIGN is set to the alignment needed by the locals area.
1551  */
1552 gint32*
1553 mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_size, guint32 *stack_align)
1554 {
1555         int i, slot, offset, size;
1556         guint32 align;
1557         MonoMethodVar *vmv;
1558         MonoInst *inst;
1559         gint32 *offsets;
1560         GList *vars = NULL, *l;
1561         StackSlotInfo *scalar_stack_slots, *vtype_stack_slots, *slot_info;
1562         MonoType *t;
1563         int nvtypes;
1564         gboolean reuse_slot;
1565
1566         if ((cfg->num_varinfo > 0) && MONO_VARINFO (cfg, 0)->interval)
1567                 return mono_allocate_stack_slots2 (cfg, backward, stack_size, stack_align);
1568
1569         scalar_stack_slots = (StackSlotInfo *)mono_mempool_alloc0 (cfg->mempool, sizeof (StackSlotInfo) * MONO_TYPE_PINNED);
1570         vtype_stack_slots = NULL;
1571         nvtypes = 0;
1572
1573         offsets = (gint32 *)mono_mempool_alloc (cfg->mempool, sizeof (gint32) * cfg->num_varinfo);
1574         for (i = 0; i < cfg->num_varinfo; ++i)
1575                 offsets [i] = -1;
1576
1577         for (i = cfg->locals_start; i < cfg->num_varinfo; i++) {
1578                 inst = cfg->varinfo [i];
1579                 vmv = MONO_VARINFO (cfg, i);
1580
1581                 if ((inst->flags & MONO_INST_IS_DEAD) || inst->opcode == OP_REGVAR || inst->opcode == OP_REGOFFSET)
1582                         continue;
1583
1584                 vars = g_list_prepend (vars, vmv);
1585         }
1586
1587         vars = mono_varlist_sort (cfg, vars, 0);
1588         offset = 0;
1589         *stack_align = sizeof(mgreg_t);
1590         for (l = vars; l; l = l->next) {
1591                 vmv = (MonoMethodVar *)l->data;
1592                 inst = cfg->varinfo [vmv->idx];
1593
1594                 t = mono_type_get_underlying_type (inst->inst_vtype);
1595                 if (cfg->gsharedvt && mini_is_gsharedvt_variable_type (t))
1596                         continue;
1597
1598                 /* inst->backend.is_pinvoke indicates native sized value types, this is used by the
1599                 * pinvoke wrappers when they call functions returning structures */
1600                 if (inst->backend.is_pinvoke && MONO_TYPE_ISSTRUCT (t) && t->type != MONO_TYPE_TYPEDBYREF) {
1601                         size = mono_class_native_size (mono_class_from_mono_type (t), &align);
1602                 } else {
1603                         int ialign;
1604
1605                         size = mini_type_stack_size (t, &ialign);
1606                         align = ialign;
1607
1608                         if (mono_class_has_failure (mono_class_from_mono_type (t)))
1609                                 mono_cfg_set_exception (cfg, MONO_EXCEPTION_TYPE_LOAD);
1610
1611                         if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type (t)))
1612                                 align = 16;
1613                 }
1614
1615                 reuse_slot = TRUE;
1616                 if (cfg->disable_reuse_stack_slots)
1617                         reuse_slot = FALSE;
1618
1619                 t = mini_get_underlying_type (t);
1620                 switch (t->type) {
1621                 case MONO_TYPE_GENERICINST:
1622                         if (!mono_type_generic_inst_is_valuetype (t)) {
1623                                 slot_info = &scalar_stack_slots [t->type];
1624                                 break;
1625                         }
1626                         /* Fall through */
1627                 case MONO_TYPE_VALUETYPE:
1628                         if (!vtype_stack_slots)
1629                                 vtype_stack_slots = (StackSlotInfo *)mono_mempool_alloc0 (cfg->mempool, sizeof (StackSlotInfo) * 256);
1630                         for (i = 0; i < nvtypes; ++i)
1631                                 if (t->data.klass == vtype_stack_slots [i].vtype)
1632                                         break;
1633                         if (i < nvtypes)
1634                                 slot_info = &vtype_stack_slots [i];
1635                         else {
1636                                 g_assert (nvtypes < 256);
1637                                 vtype_stack_slots [nvtypes].vtype = t->data.klass;
1638                                 slot_info = &vtype_stack_slots [nvtypes];
1639                                 nvtypes ++;
1640                         }
1641                         if (cfg->disable_reuse_ref_stack_slots)
1642                                 reuse_slot = FALSE;
1643                         break;
1644
1645                 case MONO_TYPE_PTR:
1646                 case MONO_TYPE_I:
1647                 case MONO_TYPE_U:
1648 #if SIZEOF_VOID_P == 4
1649                 case MONO_TYPE_I4:
1650 #else
1651                 case MONO_TYPE_I8:
1652 #endif
1653                         if (cfg->disable_ref_noref_stack_slot_share) {
1654                                 slot_info = &scalar_stack_slots [MONO_TYPE_I];
1655                                 break;
1656                         }
1657                         /* Fall through */
1658
1659                 case MONO_TYPE_CLASS:
1660                 case MONO_TYPE_OBJECT:
1661                 case MONO_TYPE_ARRAY:
1662                 case MONO_TYPE_SZARRAY:
1663                 case MONO_TYPE_STRING:
1664                         /* Share non-float stack slots of the same size */
1665                         slot_info = &scalar_stack_slots [MONO_TYPE_CLASS];
1666                         if (cfg->disable_reuse_ref_stack_slots)
1667                                 reuse_slot = FALSE;
1668                         break;
1669                 case MONO_TYPE_VAR:
1670                 case MONO_TYPE_MVAR:
1671                         slot_info = &scalar_stack_slots [t->type];
1672                         break;
1673                 default:
1674                         slot_info = &scalar_stack_slots [t->type];
1675                         break;
1676                 }
1677
1678                 slot = 0xffffff;
1679                 if (cfg->comp_done & MONO_COMP_LIVENESS) {
1680                         //printf ("START  %2d %08x %08x\n",  vmv->idx, vmv->range.first_use.abs_pos, vmv->range.last_use.abs_pos);
1681                         
1682                         /* expire old intervals in active */
1683                         while (slot_info->active) {
1684                                 MonoMethodVar *amv = (MonoMethodVar *)slot_info->active->data;
1685
1686                                 if (amv->range.last_use.abs_pos > vmv->range.first_use.abs_pos)
1687                                         break;
1688
1689                                 //printf ("EXPIR  %2d %08x %08x C%d R%d\n", amv->idx, amv->range.first_use.abs_pos, amv->range.last_use.abs_pos, amv->spill_costs, amv->reg);
1690
1691                                 slot_info->active = g_list_delete_link (slot_info->active, slot_info->active);
1692                                 slot_info->slots = g_slist_prepend_mempool (cfg->mempool, slot_info->slots, GINT_TO_POINTER (offsets [amv->idx]));
1693                         }
1694
1695                         /* 
1696                          * This also handles the case when the variable is used in an
1697                          * exception region, as liveness info is not computed there.
1698                          */
1699                         /* 
1700                          * FIXME: All valuetypes are marked as INDIRECT because of LDADDR
1701                          * opcodes.
1702                          */
1703                         if (! (inst->flags & (MONO_INST_VOLATILE|MONO_INST_INDIRECT))) {
1704                                 if (slot_info->slots) {
1705                                         slot = GPOINTER_TO_INT (slot_info->slots->data);
1706
1707                                         slot_info->slots = slot_info->slots->next;
1708                                 }
1709
1710                                 slot_info->active = mono_varlist_insert_sorted (cfg, slot_info->active, vmv, TRUE);
1711                         }
1712                 }
1713
1714                 {
1715                         static int count = 0;
1716                         count ++;
1717
1718                         /*
1719                         if (count == atoi (g_getenv ("COUNT")))
1720                                 printf ("LAST: %s\n", mono_method_full_name (cfg->method, TRUE));
1721                         if (count > atoi (g_getenv ("COUNT")))
1722                                 slot = 0xffffff;
1723                         else {
1724                                 mono_print_ins (inst);
1725                                 }
1726                         */
1727                 }
1728
1729                 if (inst->flags & MONO_INST_LMF) {
1730                         /*
1731                          * This variable represents a MonoLMF structure, which has no corresponding
1732                          * CLR type, so hard-code its size/alignment.
1733                          */
1734                         size = sizeof (MonoLMF);
1735                         align = sizeof (mgreg_t);
1736                         reuse_slot = FALSE;
1737                 }
1738
1739                 if (!reuse_slot)
1740                         slot = 0xffffff;
1741
1742                 if (slot == 0xffffff) {
1743                         /*
1744                          * Allways allocate valuetypes to sizeof (gpointer) to allow more
1745                          * efficient copying (and to work around the fact that OP_MEMCPY
1746                          * and OP_MEMSET ignores alignment).
1747                          */
1748                         if (MONO_TYPE_ISSTRUCT (t)) {
1749                                 align = MAX (align, sizeof (gpointer));
1750                                 align = MAX (align, mono_class_min_align (mono_class_from_mono_type (t)));
1751                                 /* 
1752                                  * Align the size too so the code generated for passing vtypes in
1753                                  * registers doesn't overwrite random locals.
1754                                  */
1755                                 size = (size + (align - 1)) & ~(align -1);
1756                         }
1757
1758                         if (backward) {
1759                                 offset += size;
1760                                 offset += align - 1;
1761                                 offset &= ~(align - 1);
1762                                 slot = offset;
1763                         }
1764                         else {
1765                                 offset += align - 1;
1766                                 offset &= ~(align - 1);
1767                                 slot = offset;
1768                                 offset += size;
1769                         }
1770
1771                         *stack_align = MAX (*stack_align, align);
1772                 }
1773
1774                 offsets [vmv->idx] = slot;
1775         }
1776         g_list_free (vars);
1777         for (i = 0; i < MONO_TYPE_PINNED; ++i) {
1778                 if (scalar_stack_slots [i].active)
1779                         g_list_free (scalar_stack_slots [i].active);
1780         }
1781         for (i = 0; i < nvtypes; ++i) {
1782                 if (vtype_stack_slots [i].active)
1783                         g_list_free (vtype_stack_slots [i].active);
1784         }
1785
1786         cfg->stat_locals_stack_size += offset;
1787
1788         *stack_size = offset;
1789         return offsets;
1790 }
1791
1792 #define EMUL_HIT_SHIFT 3
1793 #define EMUL_HIT_MASK ((1 << EMUL_HIT_SHIFT) - 1)
1794 /* small hit bitmap cache */
1795 static mono_byte emul_opcode_hit_cache [(OP_LAST>>EMUL_HIT_SHIFT) + 1] = {0};
1796 static short emul_opcode_num = 0;
1797 static short emul_opcode_alloced = 0;
1798 static short *emul_opcode_opcodes;
1799 static MonoJitICallInfo **emul_opcode_map;
1800
1801 MonoJitICallInfo *
1802 mono_find_jit_opcode_emulation (int opcode)
1803 {
1804         g_assert (opcode >= 0 && opcode <= OP_LAST);
1805         if (emul_opcode_hit_cache [opcode >> (EMUL_HIT_SHIFT + 3)] & (1 << (opcode & EMUL_HIT_MASK))) {
1806                 int i;
1807                 for (i = 0; i < emul_opcode_num; ++i) {
1808                         if (emul_opcode_opcodes [i] == opcode)
1809                                 return emul_opcode_map [i];
1810                 }
1811         }
1812         return NULL;
1813 }
1814
1815 void
1816 mini_register_opcode_emulation (int opcode, const char *name, const char *sigstr, gpointer func, const char *symbol, gboolean no_throw)
1817 {
1818         MonoJitICallInfo *info;
1819         MonoMethodSignature *sig = mono_create_icall_signature (sigstr);
1820
1821         g_assert (!sig->hasthis);
1822         g_assert (sig->param_count < 3);
1823
1824         /* Opcode emulation functions are assumed to don't call mono_raise_exception () */
1825         info = mono_register_jit_icall_full (func, name, sig, no_throw, TRUE, symbol);
1826
1827         if (emul_opcode_num >= emul_opcode_alloced) {
1828                 int incr = emul_opcode_alloced? emul_opcode_alloced/2: 16;
1829                 emul_opcode_alloced += incr;
1830                 emul_opcode_map = (MonoJitICallInfo **)g_realloc (emul_opcode_map, sizeof (emul_opcode_map [0]) * emul_opcode_alloced);
1831                 emul_opcode_opcodes = (short *)g_realloc (emul_opcode_opcodes, sizeof (emul_opcode_opcodes [0]) * emul_opcode_alloced);
1832         }
1833         emul_opcode_map [emul_opcode_num] = info;
1834         emul_opcode_opcodes [emul_opcode_num] = opcode;
1835         emul_opcode_num++;
1836         emul_opcode_hit_cache [opcode >> (EMUL_HIT_SHIFT + 3)] |= (1 << (opcode & EMUL_HIT_MASK));
1837 }
1838
1839 static void
1840 print_dfn (MonoCompile *cfg)
1841 {
1842         int i, j;
1843         char *code;
1844         MonoBasicBlock *bb;
1845         MonoInst *c;
1846
1847         {
1848                 char *method_name = mono_method_full_name (cfg->method, TRUE);
1849                 g_print ("IR code for method %s\n", method_name);
1850                 g_free (method_name);
1851         }
1852
1853         for (i = 0; i < cfg->num_bblocks; ++i) {
1854                 bb = cfg->bblocks [i];
1855                 /*if (bb->cil_code) {
1856                         char* code1, *code2;
1857                         code1 = mono_disasm_code_one (NULL, cfg->method, bb->cil_code, NULL);
1858                         if (bb->last_ins->cil_code)
1859                                 code2 = mono_disasm_code_one (NULL, cfg->method, bb->last_ins->cil_code, NULL);
1860                         else
1861                                 code2 = g_strdup ("");
1862
1863                         code1 [strlen (code1) - 1] = 0;
1864                         code = g_strdup_printf ("%s -> %s", code1, code2);
1865                         g_free (code1);
1866                         g_free (code2);
1867                 } else*/
1868                         code = g_strdup ("\n");
1869                 g_print ("\nBB%d (%d) (len: %d): %s", bb->block_num, i, bb->cil_length, code);
1870                 MONO_BB_FOR_EACH_INS (bb, c) {
1871                         mono_print_ins_index (-1, c);
1872                 }
1873
1874                 g_print ("\tprev:");
1875                 for (j = 0; j < bb->in_count; ++j) {
1876                         g_print (" BB%d", bb->in_bb [j]->block_num);
1877                 }
1878                 g_print ("\t\tsucc:");
1879                 for (j = 0; j < bb->out_count; ++j) {
1880                         g_print (" BB%d", bb->out_bb [j]->block_num);
1881                 }
1882                 g_print ("\n\tidom: BB%d\n", bb->idom? bb->idom->block_num: -1);
1883
1884                 if (bb->idom)
1885                         g_assert (mono_bitset_test_fast (bb->dominators, bb->idom->dfn));
1886
1887                 if (bb->dominators)
1888                         mono_blockset_print (cfg, bb->dominators, "\tdominators", bb->idom? bb->idom->dfn: -1);
1889                 if (bb->dfrontier)
1890                         mono_blockset_print (cfg, bb->dfrontier, "\tdfrontier", -1);
1891                 g_free (code);
1892         }
1893
1894         g_print ("\n");
1895 }
1896
1897 void
1898 mono_bblock_add_inst (MonoBasicBlock *bb, MonoInst *inst)
1899 {
1900         MONO_ADD_INS (bb, inst);
1901 }
1902
1903 void
1904 mono_bblock_insert_after_ins (MonoBasicBlock *bb, MonoInst *ins, MonoInst *ins_to_insert)
1905 {
1906         if (ins == NULL) {
1907                 ins = bb->code;
1908                 bb->code = ins_to_insert;
1909
1910                 /* Link with next */
1911                 ins_to_insert->next = ins;
1912                 if (ins)
1913                         ins->prev = ins_to_insert;
1914
1915                 if (bb->last_ins == NULL)
1916                         bb->last_ins = ins_to_insert;
1917         } else {
1918                 /* Link with next */
1919                 ins_to_insert->next = ins->next;
1920                 if (ins->next)
1921                         ins->next->prev = ins_to_insert;
1922
1923                 /* Link with previous */
1924                 ins->next = ins_to_insert;
1925                 ins_to_insert->prev = ins;
1926
1927                 if (bb->last_ins == ins)
1928                         bb->last_ins = ins_to_insert;
1929         }
1930 }
1931
1932 void
1933 mono_bblock_insert_before_ins (MonoBasicBlock *bb, MonoInst *ins, MonoInst *ins_to_insert)
1934 {
1935         if (ins == NULL) {
1936                 ins = bb->code;
1937                 if (ins)
1938                         ins->prev = ins_to_insert;
1939                 bb->code = ins_to_insert;
1940                 ins_to_insert->next = ins;
1941                 if (bb->last_ins == NULL)
1942                         bb->last_ins = ins_to_insert;
1943         } else {
1944                 /* Link with previous */
1945                 if (ins->prev)
1946                         ins->prev->next = ins_to_insert;
1947                 ins_to_insert->prev = ins->prev;
1948
1949                 /* Link with next */
1950                 ins->prev = ins_to_insert;
1951                 ins_to_insert->next = ins;
1952
1953                 if (bb->code == ins)
1954                         bb->code = ins_to_insert;
1955         }
1956 }
1957
1958 /*
1959  * mono_verify_bblock:
1960  *
1961  *   Verify that the next and prev pointers are consistent inside the instructions in BB.
1962  */
1963 void
1964 mono_verify_bblock (MonoBasicBlock *bb)
1965 {
1966         MonoInst *ins, *prev;
1967
1968         prev = NULL;
1969         for (ins = bb->code; ins; ins = ins->next) {
1970                 g_assert (ins->prev == prev);
1971                 prev = ins;
1972         }
1973         if (bb->last_ins)
1974                 g_assert (!bb->last_ins->next);
1975 }
1976
1977 /*
1978  * mono_verify_cfg:
1979  *
1980  *   Perform consistency checks on the JIT data structures and the IR
1981  */
1982 void
1983 mono_verify_cfg (MonoCompile *cfg)
1984 {
1985         MonoBasicBlock *bb;
1986
1987         for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
1988                 mono_verify_bblock (bb);
1989 }
1990
1991 void
1992 mono_destroy_compile (MonoCompile *cfg)
1993 {
1994         GSList *l;
1995
1996         if (cfg->header)
1997                 mono_metadata_free_mh (cfg->header);
1998         //mono_mempool_stats (cfg->mempool);
1999         mono_free_loop_info (cfg);
2000         if (cfg->rs)
2001                 mono_regstate_free (cfg->rs);
2002         if (cfg->spvars)
2003                 g_hash_table_destroy (cfg->spvars);
2004         if (cfg->exvars)
2005                 g_hash_table_destroy (cfg->exvars);
2006         for (l = cfg->headers_to_free; l; l = l->next)
2007                 mono_metadata_free_mh ((MonoMethodHeader *)l->data);
2008         g_list_free (cfg->ldstr_list);
2009         g_hash_table_destroy (cfg->token_info_hash);
2010         if (cfg->abs_patches)
2011                 g_hash_table_destroy (cfg->abs_patches);
2012         mono_mempool_destroy (cfg->mempool);
2013
2014         mono_debug_free_method (cfg);
2015
2016         g_free (cfg->varinfo);
2017         g_free (cfg->vars);
2018         g_free (cfg->exception_message);
2019         g_free (cfg);
2020 }
2021
2022 static MonoInst*
2023 mono_create_tls_get_offset (MonoCompile *cfg, int offset)
2024 {
2025         MonoInst* ins;
2026
2027         if (!cfg->backend->have_tls_get)
2028                 return NULL;
2029
2030         if (offset == -1)
2031                 return NULL;
2032
2033         MONO_INST_NEW (cfg, ins, OP_TLS_GET);
2034         ins->dreg = mono_alloc_preg (cfg);
2035         ins->inst_offset = offset;
2036         return ins;
2037 }
2038
2039 gboolean
2040 mini_tls_get_supported (MonoCompile *cfg, MonoTlsKey key)
2041 {
2042         if (!cfg->backend->have_tls_get)
2043                 return FALSE;
2044
2045         if (cfg->compile_aot)
2046                 return cfg->backend->have_tls_get_reg;
2047         else
2048                 return mini_get_tls_offset (key) != -1;
2049 }
2050
2051 MonoInst*
2052 mono_create_tls_get (MonoCompile *cfg, MonoTlsKey key)
2053 {
2054         if (!cfg->backend->have_tls_get)
2055                 return NULL;
2056
2057         /*
2058          * TLS offsets might be different at AOT time, so load them from a GOT slot and
2059          * use a different opcode.
2060          */
2061         if (cfg->compile_aot) {
2062                 if (cfg->backend->have_tls_get_reg) {
2063                         MonoInst *ins, *c;
2064
2065                         EMIT_NEW_TLS_OFFSETCONST (cfg, c, key);
2066                         MONO_INST_NEW (cfg, ins, OP_TLS_GET_REG);
2067                         ins->dreg = mono_alloc_preg (cfg);
2068                         ins->sreg1 = c->dreg;
2069                         return ins;
2070                 } else {
2071                         return NULL;
2072                 }
2073         }
2074
2075         return mono_create_tls_get_offset (cfg, mini_get_tls_offset (key));
2076 }
2077
2078 MonoInst*
2079 mono_get_jit_tls_intrinsic (MonoCompile *cfg)
2080 {
2081         return mono_create_tls_get (cfg, TLS_KEY_JIT_TLS);
2082 }
2083
2084 MonoInst*
2085 mono_get_domain_intrinsic (MonoCompile* cfg)
2086 {
2087         return mono_create_tls_get (cfg, TLS_KEY_DOMAIN);
2088 }
2089
2090 MonoInst*
2091 mono_get_thread_intrinsic (MonoCompile* cfg)
2092 {
2093         return mono_create_tls_get (cfg, TLS_KEY_THREAD);
2094 }
2095
2096 MonoInst*
2097 mono_get_lmf_intrinsic (MonoCompile* cfg)
2098 {
2099         return mono_create_tls_get (cfg, TLS_KEY_LMF);
2100 }
2101
2102 MonoInst*
2103 mono_get_lmf_addr_intrinsic (MonoCompile* cfg)
2104 {
2105         return mono_create_tls_get (cfg, TLS_KEY_LMF_ADDR);
2106 }
2107
2108 void
2109 mono_add_patch_info (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target)
2110 {
2111         MonoJumpInfo *ji = (MonoJumpInfo *)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoJumpInfo));
2112
2113         ji->ip.i = ip;
2114         ji->type = type;
2115         ji->data.target = target;
2116         ji->next = cfg->patch_info;
2117
2118         cfg->patch_info = ji;
2119 }
2120
2121 void
2122 mono_add_patch_info_rel (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target, int relocation)
2123 {
2124         MonoJumpInfo *ji = (MonoJumpInfo *)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoJumpInfo));
2125
2126         ji->ip.i = ip;
2127         ji->type = type;
2128         ji->relocation = relocation;
2129         ji->data.target = target;
2130         ji->next = cfg->patch_info;
2131
2132         cfg->patch_info = ji;
2133 }
2134
2135 void
2136 mono_remove_patch_info (MonoCompile *cfg, int ip)
2137 {
2138         MonoJumpInfo **ji = &cfg->patch_info;
2139
2140         while (*ji) {
2141                 if ((*ji)->ip.i == ip)
2142                         *ji = (*ji)->next;
2143                 else
2144                         ji = &((*ji)->next);
2145         }
2146 }
2147
2148 void
2149 mono_add_seq_point (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, int native_offset)
2150 {
2151         ins->inst_offset = native_offset;
2152         g_ptr_array_add (cfg->seq_points, ins);
2153         if (bb) {
2154                 bb->seq_points = g_slist_prepend_mempool (cfg->mempool, bb->seq_points, ins);
2155                 bb->last_seq_point = ins;
2156         }
2157 }
2158
2159 void
2160 mono_add_var_location (MonoCompile *cfg, MonoInst *var, gboolean is_reg, int reg, int offset, int from, int to)
2161 {
2162         MonoDwarfLocListEntry *entry = (MonoDwarfLocListEntry *)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoDwarfLocListEntry));
2163
2164         if (is_reg)
2165                 g_assert (offset == 0);
2166
2167         entry->is_reg = is_reg;
2168         entry->reg = reg;
2169         entry->offset = offset;
2170         entry->from = from;
2171         entry->to = to;
2172
2173         if (var == cfg->args [0])
2174                 cfg->this_loclist = g_slist_append_mempool (cfg->mempool, cfg->this_loclist, entry);
2175         else if (var == cfg->rgctx_var)
2176                 cfg->rgctx_loclist = g_slist_append_mempool (cfg->mempool, cfg->rgctx_loclist, entry);
2177 }
2178
2179 static void
2180 mono_compile_create_vars (MonoCompile *cfg)
2181 {
2182         MonoMethodSignature *sig;
2183         MonoMethodHeader *header;
2184         int i;
2185
2186         header = cfg->header;
2187
2188         sig = mono_method_signature (cfg->method);
2189         
2190         if (!MONO_TYPE_IS_VOID (sig->ret)) {
2191                 cfg->ret = mono_compile_create_var (cfg, sig->ret, OP_ARG);
2192                 /* Inhibit optimizations */
2193                 cfg->ret->flags |= MONO_INST_VOLATILE;
2194         }
2195         if (cfg->verbose_level > 2)
2196                 g_print ("creating vars\n");
2197
2198         cfg->args = (MonoInst **)mono_mempool_alloc0 (cfg->mempool, (sig->param_count + sig->hasthis) * sizeof (MonoInst*));
2199
2200         if (sig->hasthis)
2201                 cfg->args [0] = mono_compile_create_var (cfg, &cfg->method->klass->this_arg, OP_ARG);
2202
2203         for (i = 0; i < sig->param_count; ++i) {
2204                 cfg->args [i + sig->hasthis] = mono_compile_create_var (cfg, sig->params [i], OP_ARG);
2205         }
2206
2207         if (cfg->verbose_level > 2) {
2208                 if (cfg->ret) {
2209                         printf ("\treturn : ");
2210                         mono_print_ins (cfg->ret);
2211                 }
2212
2213                 if (sig->hasthis) {
2214                         printf ("\tthis: ");
2215                         mono_print_ins (cfg->args [0]);
2216                 }
2217
2218                 for (i = 0; i < sig->param_count; ++i) {
2219                         printf ("\targ [%d]: ", i);
2220                         mono_print_ins (cfg->args [i + sig->hasthis]);
2221                 }
2222         }
2223
2224         cfg->locals_start = cfg->num_varinfo;
2225         cfg->locals = (MonoInst **)mono_mempool_alloc0 (cfg->mempool, header->num_locals * sizeof (MonoInst*));
2226
2227         if (cfg->verbose_level > 2)
2228                 g_print ("creating locals\n");
2229
2230         for (i = 0; i < header->num_locals; ++i)
2231                 cfg->locals [i] = mono_compile_create_var (cfg, header->locals [i], OP_LOCAL);
2232
2233         if (cfg->verbose_level > 2)
2234                 g_print ("locals done\n");
2235
2236 #ifdef ENABLE_LLVM
2237         if (COMPILE_LLVM (cfg))
2238                 mono_llvm_create_vars (cfg);
2239         else
2240                 mono_arch_create_vars (cfg);
2241 #else
2242         mono_arch_create_vars (cfg);
2243 #endif
2244
2245         if (cfg->method->save_lmf && cfg->create_lmf_var) {
2246                 MonoInst *lmf_var = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL);
2247                 lmf_var->flags |= MONO_INST_VOLATILE;
2248                 lmf_var->flags |= MONO_INST_LMF;
2249                 cfg->lmf_var = lmf_var;
2250         }
2251 }
2252
2253 void
2254 mono_print_code (MonoCompile *cfg, const char* msg)
2255 {
2256         MonoBasicBlock *bb;
2257         
2258         for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
2259                 mono_print_bb (bb, msg);
2260 }
2261
2262 static void
2263 mono_postprocess_patches (MonoCompile *cfg)
2264 {
2265         MonoJumpInfo *patch_info;
2266         int i;
2267
2268         for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) {
2269                 switch (patch_info->type) {
2270                 case MONO_PATCH_INFO_ABS: {
2271                         MonoJitICallInfo *info = mono_find_jit_icall_by_addr (patch_info->data.target);
2272
2273                         /*
2274                          * Change patches of type MONO_PATCH_INFO_ABS into patches describing the 
2275                          * absolute address.
2276                          */
2277                         if (info) {
2278                                 //printf ("TEST %s %p\n", info->name, patch_info->data.target);
2279                                 /* for these array methods we currently register the same function pointer
2280                                  * since it's a vararg function. But this means that mono_find_jit_icall_by_addr ()
2281                                  * will return the incorrect one depending on the order they are registered.
2282                                  * See tests/test-arr.cs
2283                                  */
2284                                 if (strstr (info->name, "ves_array_new_va_") == NULL && strstr (info->name, "ves_array_element_address_") == NULL) {
2285                                         patch_info->type = MONO_PATCH_INFO_INTERNAL_METHOD;
2286                                         patch_info->data.name = info->name;
2287                                 }
2288                         }
2289
2290                         if (patch_info->type == MONO_PATCH_INFO_ABS) {
2291                                 if (cfg->abs_patches) {
2292                                         MonoJumpInfo *abs_ji = (MonoJumpInfo *)g_hash_table_lookup (cfg->abs_patches, patch_info->data.target);
2293                                         if (abs_ji) {
2294                                                 patch_info->type = abs_ji->type;
2295                                                 patch_info->data.target = abs_ji->data.target;
2296                                         }
2297                                 }
2298                         }
2299
2300                         break;
2301                 }
2302                 case MONO_PATCH_INFO_SWITCH: {
2303                         gpointer *table;
2304 #if defined(__native_client__) && defined(__native_client_codegen__)
2305                         /* This memory will leak.  */
2306                         /* TODO: can we free this when  */
2307                         /* making the final jump table? */
2308                         table = g_malloc0 (sizeof(gpointer) * patch_info->data.table->table_size);
2309 #else
2310                         if (cfg->method->dynamic) {
2311                                 table = (void **)mono_code_manager_reserve (cfg->dynamic_info->code_mp, sizeof (gpointer) * patch_info->data.table->table_size);
2312                         } else {
2313                                 table = (void **)mono_domain_code_reserve (cfg->domain, sizeof (gpointer) * patch_info->data.table->table_size);
2314                         }
2315 #endif
2316
2317                         for (i = 0; i < patch_info->data.table->table_size; i++) {
2318                                 /* Might be NULL if the switch is eliminated */
2319                                 if (patch_info->data.table->table [i]) {
2320                                         g_assert (patch_info->data.table->table [i]->native_offset);
2321                                         table [i] = GINT_TO_POINTER (patch_info->data.table->table [i]->native_offset);
2322                                 } else {
2323                                         table [i] = NULL;
2324                                 }
2325                         }
2326                         patch_info->data.table->table = (MonoBasicBlock**)table;
2327                         break;
2328                 }
2329                 case MONO_PATCH_INFO_METHOD_JUMP: {
2330                         MonoJumpList *jlist;
2331                         MonoDomain *domain = cfg->domain;
2332                         unsigned char *ip = cfg->native_code + patch_info->ip.i;
2333 #if defined(__native_client__) && defined(__native_client_codegen__)
2334                         /* When this jump target gets evaluated, the method */
2335                         /* will be installed in the dynamic code section,   */
2336                         /* not at the location of cfg->native_code.         */
2337                         ip = nacl_inverse_modify_patch_target (cfg->native_code) + patch_info->ip.i;
2338 #endif
2339
2340                         mono_domain_lock (domain);
2341                         jlist = (MonoJumpList *)g_hash_table_lookup (domain_jit_info (domain)->jump_target_hash, patch_info->data.method);
2342                         if (!jlist) {
2343                                 jlist = (MonoJumpList *)mono_domain_alloc0 (domain, sizeof (MonoJumpList));
2344                                 g_hash_table_insert (domain_jit_info (domain)->jump_target_hash, patch_info->data.method, jlist);
2345                         }
2346                         jlist->list = g_slist_prepend (jlist->list, ip);
2347                         mono_domain_unlock (domain);
2348                         break;
2349                 }
2350                 default:
2351                         /* do nothing */
2352                         break;
2353                 }
2354         }
2355 }
2356
2357 void
2358 mono_codegen (MonoCompile *cfg)
2359 {
2360         MonoBasicBlock *bb;
2361         int max_epilog_size;
2362         guint8 *code;
2363         MonoDomain *code_domain;
2364         guint unwindlen = 0;
2365
2366         if (mono_using_xdebug)
2367                 /*
2368                  * Recent gdb versions have trouble processing symbol files containing
2369                  * overlapping address ranges, so allocate all code from the code manager
2370                  * of the root domain. (#666152).
2371                  */
2372                 code_domain = mono_get_root_domain ();
2373         else
2374                 code_domain = cfg->domain;
2375
2376 #if defined(__native_client_codegen__) && defined(__native_client__)
2377         void *code_dest;
2378
2379         /* This keeps patch targets from being transformed during
2380          * ordinary method compilation, for local branches and jumps.
2381          */
2382         nacl_allow_target_modification (FALSE);
2383 #endif
2384
2385         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
2386                 cfg->spill_count = 0;
2387                 /* we reuse dfn here */
2388                 /* bb->dfn = bb_count++; */
2389
2390                 mono_arch_lowering_pass (cfg, bb);
2391
2392                 if (cfg->opt & MONO_OPT_PEEPHOLE)
2393                         mono_arch_peephole_pass_1 (cfg, bb);
2394
2395                 mono_local_regalloc (cfg, bb);
2396
2397                 if (cfg->opt & MONO_OPT_PEEPHOLE)
2398                         mono_arch_peephole_pass_2 (cfg, bb);
2399
2400                 if (cfg->gen_seq_points && !cfg->gen_sdb_seq_points)
2401                         mono_bb_deduplicate_op_il_seq_points (cfg, bb);
2402         }
2403
2404         if (cfg->prof_options & MONO_PROFILE_COVERAGE)
2405                 cfg->coverage_info = mono_profiler_coverage_alloc (cfg->method, cfg->num_bblocks);
2406
2407         code = mono_arch_emit_prolog (cfg);
2408
2409         cfg->code_len = code - cfg->native_code;
2410         cfg->prolog_end = cfg->code_len;
2411         cfg->cfa_reg = cfg->cur_cfa_reg;
2412         cfg->cfa_offset = cfg->cur_cfa_offset;
2413
2414         mono_debug_open_method (cfg);
2415
2416         /* emit code all basic blocks */
2417         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
2418                 bb->native_offset = cfg->code_len;
2419                 bb->real_native_offset = cfg->code_len;
2420                 //if ((bb == cfg->bb_entry) || !(bb->region == -1 && !bb->dfn))
2421                         mono_arch_output_basic_block (cfg, bb);
2422                 bb->native_length = cfg->code_len - bb->native_offset;
2423
2424                 if (bb == cfg->bb_exit) {
2425                         cfg->epilog_begin = cfg->code_len;
2426                         mono_arch_emit_epilog (cfg);
2427                         cfg->epilog_end = cfg->code_len;
2428                 }
2429         }
2430
2431 #ifdef __native_client_codegen__
2432         mono_nacl_fix_patches (cfg->native_code, cfg->patch_info);
2433 #endif
2434         mono_arch_emit_exceptions (cfg);
2435
2436         max_epilog_size = 0;
2437
2438         /* we always allocate code in cfg->domain->code_mp to increase locality */
2439         cfg->code_size = cfg->code_len + max_epilog_size;
2440 #ifdef __native_client_codegen__
2441         cfg->code_size = NACL_BUNDLE_ALIGN_UP (cfg->code_size);
2442 #endif
2443         /* fixme: align to MONO_ARCH_CODE_ALIGNMENT */
2444
2445 #ifdef MONO_ARCH_HAVE_UNWIND_TABLE
2446         unwindlen = mono_arch_unwindinfo_get_size (cfg->arch.unwindinfo);
2447 #endif
2448
2449         if (cfg->method->dynamic) {
2450                 /* Allocate the code into a separate memory pool so it can be freed */
2451                 cfg->dynamic_info = g_new0 (MonoJitDynamicMethodInfo, 1);
2452                 cfg->dynamic_info->code_mp = mono_code_manager_new_dynamic ();
2453                 mono_domain_lock (cfg->domain);
2454                 mono_dynamic_code_hash_insert (cfg->domain, cfg->method, cfg->dynamic_info);
2455                 mono_domain_unlock (cfg->domain);
2456
2457                 if (mono_using_xdebug)
2458                         /* See the comment for cfg->code_domain */
2459                         code = (guint8 *)mono_domain_code_reserve (code_domain, cfg->code_size + cfg->thunk_area + unwindlen);
2460                 else
2461                         code = (guint8 *)mono_code_manager_reserve (cfg->dynamic_info->code_mp, cfg->code_size + cfg->thunk_area + unwindlen);
2462         } else {
2463                 code = (guint8 *)mono_domain_code_reserve (code_domain, cfg->code_size + cfg->thunk_area + unwindlen);
2464         }
2465 #if defined(__native_client_codegen__) && defined(__native_client__)
2466         nacl_allow_target_modification (TRUE);
2467 #endif
2468         if (cfg->thunk_area) {
2469                 cfg->thunks_offset = cfg->code_size + unwindlen;
2470                 cfg->thunks = code + cfg->thunks_offset;
2471                 memset (cfg->thunks, 0, cfg->thunk_area);
2472         }
2473
2474         g_assert (code);
2475         memcpy (code, cfg->native_code, cfg->code_len);
2476 #if defined(__default_codegen__)
2477         g_free (cfg->native_code);
2478 #elif defined(__native_client_codegen__)
2479         if (cfg->native_code_alloc) {
2480                 g_free (cfg->native_code_alloc);
2481                 cfg->native_code_alloc = 0;
2482         }
2483         else if (cfg->native_code) {
2484                 g_free (cfg->native_code);
2485         }
2486 #endif /* __native_client_codegen__ */
2487         cfg->native_code = code;
2488         code = cfg->native_code + cfg->code_len;
2489   
2490         /* g_assert (((int)cfg->native_code & (MONO_ARCH_CODE_ALIGNMENT - 1)) == 0); */
2491         mono_postprocess_patches (cfg);
2492
2493 #ifdef VALGRIND_JIT_REGISTER_MAP
2494         if (valgrind_register){
2495                 char* nm = mono_method_full_name (cfg->method, TRUE);
2496                 VALGRIND_JIT_REGISTER_MAP (nm, cfg->native_code, cfg->native_code + cfg->code_len);
2497                 g_free (nm);
2498         }
2499 #endif
2500  
2501         if (cfg->verbose_level > 0) {
2502                 char* nm = mono_method_get_full_name (cfg->method);
2503                 char *opt_descr = mono_opt_descr (cfg->opt);
2504                 g_print ("Method %s emitted at %p to %p (code length %d) [%s] with opts %s\n", 
2505                                  nm, 
2506                                  cfg->native_code, cfg->native_code + cfg->code_len, cfg->code_len, cfg->domain->friendly_name,
2507                                  opt_descr);
2508                 g_free (nm);
2509                 g_free (opt_descr);
2510         }
2511
2512         {
2513                 gboolean is_generic = FALSE;
2514
2515                 if (cfg->method->is_inflated || mono_method_get_generic_container (cfg->method) ||
2516                                 cfg->method->klass->generic_container || cfg->method->klass->generic_class) {
2517                         is_generic = TRUE;
2518                 }
2519
2520                 if (cfg->gshared)
2521                         g_assert (is_generic);
2522         }
2523
2524 #ifdef MONO_ARCH_HAVE_SAVE_UNWIND_INFO
2525         mono_arch_save_unwind_info (cfg);
2526 #endif
2527
2528 #if defined(__native_client_codegen__) && defined(__native_client__)
2529         if (!cfg->compile_aot) {
2530                 if (cfg->method->dynamic) {
2531                         code_dest = nacl_code_manager_get_code_dest(cfg->dynamic_info->code_mp, cfg->native_code);
2532                 } else {
2533                         code_dest = nacl_domain_get_code_dest(cfg->domain, cfg->native_code);
2534                 }
2535         }
2536 #endif
2537
2538 #if defined(__native_client_codegen__)
2539         mono_nacl_fix_patches (cfg->native_code, cfg->patch_info);
2540 #endif
2541
2542 #ifdef MONO_ARCH_HAVE_PATCH_CODE_NEW
2543         {
2544                 MonoJumpInfo *ji;
2545                 gpointer target;
2546
2547                 for (ji = cfg->patch_info; ji; ji = ji->next) {
2548                         if (cfg->compile_aot) {
2549                                 switch (ji->type) {
2550                                 case MONO_PATCH_INFO_BB:
2551                                 case MONO_PATCH_INFO_LABEL:
2552                                         break;
2553                                 default:
2554                                         /* No need to patch these */
2555                                         continue;
2556                                 }
2557                         }
2558
2559                         if (ji->type == MONO_PATCH_INFO_NONE)
2560                                 continue;
2561
2562                         target = mono_resolve_patch_target (cfg->method, cfg->domain, cfg->native_code, ji, cfg->run_cctors, &cfg->error);
2563                         if (!mono_error_ok (&cfg->error)) {
2564                                 mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
2565                                 return;
2566                         }
2567                         mono_arch_patch_code_new (cfg, cfg->domain, cfg->native_code, ji, target);
2568                 }
2569         }
2570 #else
2571         mono_arch_patch_code (cfg, cfg->method, cfg->domain, cfg->native_code, cfg->patch_info, cfg->run_cctors);
2572 #endif
2573
2574         if (cfg->method->dynamic) {
2575                 if (mono_using_xdebug)
2576                         mono_domain_code_commit (code_domain, cfg->native_code, cfg->code_size, cfg->code_len);
2577                 else
2578                         mono_code_manager_commit (cfg->dynamic_info->code_mp, cfg->native_code, cfg->code_size, cfg->code_len);
2579         } else {
2580                 mono_domain_code_commit (code_domain, cfg->native_code, cfg->code_size, cfg->code_len);
2581         }
2582 #if defined(__native_client_codegen__) && defined(__native_client__)
2583         cfg->native_code = code_dest;
2584 #endif
2585         mono_profiler_code_buffer_new (cfg->native_code, cfg->code_len, MONO_PROFILER_CODE_BUFFER_METHOD, cfg->method);
2586         
2587         mono_arch_flush_icache (cfg->native_code, cfg->code_len);
2588
2589         mono_debug_close_method (cfg);
2590
2591 #ifdef MONO_ARCH_HAVE_UNWIND_TABLE
2592         mono_arch_unwindinfo_install_unwind_info (&cfg->arch.unwindinfo, cfg->native_code, cfg->code_len);
2593 #endif
2594 }
2595
2596 static void
2597 compute_reachable (MonoBasicBlock *bb)
2598 {
2599         int i;
2600
2601         if (!(bb->flags & BB_VISITED)) {
2602                 bb->flags |= BB_VISITED;
2603                 for (i = 0; i < bb->out_count; ++i)
2604                         compute_reachable (bb->out_bb [i]);
2605         }
2606 }
2607
2608 static void mono_bb_ordering (MonoCompile *cfg)
2609 {
2610         int dfn = 0;
2611         /* Depth-first ordering on basic blocks */
2612         cfg->bblocks = (MonoBasicBlock **)mono_mempool_alloc (cfg->mempool, sizeof (MonoBasicBlock*) * (cfg->num_bblocks + 1));
2613
2614         cfg->max_block_num = cfg->num_bblocks;
2615
2616         df_visit (cfg->bb_entry, &dfn, cfg->bblocks);
2617         if (cfg->num_bblocks != dfn + 1) {
2618                 MonoBasicBlock *bb;
2619
2620                 cfg->num_bblocks = dfn + 1;
2621
2622                 /* remove unreachable code, because the code in them may be 
2623                  * inconsistent  (access to dead variables for example) */
2624                 for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
2625                         bb->flags &= ~BB_VISITED;
2626                 compute_reachable (cfg->bb_entry);
2627                 for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
2628                         if (bb->flags & BB_EXCEPTION_HANDLER)
2629                                 compute_reachable (bb);
2630                 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
2631                         if (!(bb->flags & BB_VISITED)) {
2632                                 if (cfg->verbose_level > 1)
2633                                         g_print ("found unreachable code in BB%d\n", bb->block_num);
2634                                 bb->code = bb->last_ins = NULL;
2635                                 while (bb->out_count)
2636                                         mono_unlink_bblock (cfg, bb, bb->out_bb [0]);
2637                         }
2638                 }
2639                 for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
2640                         bb->flags &= ~BB_VISITED;
2641         }
2642 }
2643
2644 static void
2645 mono_handle_out_of_line_bblock (MonoCompile *cfg)
2646 {
2647         MonoBasicBlock *bb;
2648         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
2649                 if (bb->next_bb && bb->next_bb->out_of_line && bb->last_ins && !MONO_IS_BRANCH_OP (bb->last_ins)) {
2650                         MonoInst *ins;
2651                         MONO_INST_NEW (cfg, ins, OP_BR);
2652                         MONO_ADD_INS (bb, ins);
2653                         ins->inst_target_bb = bb->next_bb;
2654                 }
2655         }
2656 }
2657
2658 static MonoJitInfo*
2659 create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
2660 {
2661         GSList *tmp;
2662         MonoMethodHeader *header;
2663         MonoJitInfo *jinfo;
2664         MonoJitInfoFlags flags = JIT_INFO_NONE;
2665         int num_clauses, num_holes = 0;
2666         guint32 stack_size = 0;
2667
2668         g_assert (method_to_compile == cfg->method);
2669         header = cfg->header;
2670
2671         if (cfg->gshared)
2672                 flags = (MonoJitInfoFlags)(flags | JIT_INFO_HAS_GENERIC_JIT_INFO);
2673
2674         if (cfg->arch_eh_jit_info) {
2675                 MonoJitArgumentInfo *arg_info;
2676                 MonoMethodSignature *sig = mono_method_signature (cfg->method_to_register);
2677
2678                 /*
2679                  * This cannot be computed during stack walking, as
2680                  * mono_arch_get_argument_info () is not signal safe.
2681                  */
2682                 arg_info = g_newa (MonoJitArgumentInfo, sig->param_count + 1);
2683                 stack_size = mono_arch_get_argument_info (sig, sig->param_count, arg_info);
2684
2685                 if (stack_size)
2686                         flags = (MonoJitInfoFlags)(flags | JIT_INFO_HAS_ARCH_EH_INFO);
2687         }
2688
2689         if (cfg->has_unwind_info_for_epilog && !(flags & JIT_INFO_HAS_ARCH_EH_INFO))
2690                 flags = (MonoJitInfoFlags)(flags | JIT_INFO_HAS_ARCH_EH_INFO);
2691
2692         if (cfg->thunk_area)
2693                 flags = (MonoJitInfoFlags)(flags | JIT_INFO_HAS_THUNK_INFO);
2694
2695         if (cfg->try_block_holes) {
2696                 for (tmp = cfg->try_block_holes; tmp; tmp = tmp->next) {
2697                         TryBlockHole *hole = (TryBlockHole *)tmp->data;
2698                         MonoExceptionClause *ec = hole->clause;
2699                         int hole_end = hole->basic_block->native_offset + hole->basic_block->native_length;
2700                         MonoBasicBlock *clause_last_bb = cfg->cil_offset_to_bb [ec->try_offset + ec->try_len];
2701                         g_assert (clause_last_bb);
2702
2703                         /* Holes at the end of a try region can be represented by simply reducing the size of the block itself.*/
2704                         if (clause_last_bb->native_offset != hole_end)
2705                                 ++num_holes;
2706                 }
2707                 if (num_holes)
2708                         flags = (MonoJitInfoFlags)(flags | JIT_INFO_HAS_TRY_BLOCK_HOLES);
2709                 if (G_UNLIKELY (cfg->verbose_level >= 4))
2710                         printf ("Number of try block holes %d\n", num_holes);
2711         }
2712
2713         if (COMPILE_LLVM (cfg))
2714                 num_clauses = cfg->llvm_ex_info_len;
2715         else
2716                 num_clauses = header->num_clauses;
2717
2718         if (cfg->method->dynamic)
2719                 jinfo = (MonoJitInfo *)g_malloc0 (mono_jit_info_size (flags, num_clauses, num_holes));
2720         else
2721                 jinfo = (MonoJitInfo *)mono_domain_alloc0 (cfg->domain, mono_jit_info_size (flags, num_clauses, num_holes));
2722         mono_jit_info_init (jinfo, cfg->method_to_register, cfg->native_code, cfg->code_len, flags, num_clauses, num_holes);
2723         jinfo->domain_neutral = (cfg->opt & MONO_OPT_SHARED) != 0;
2724
2725         if (COMPILE_LLVM (cfg))
2726                 jinfo->from_llvm = TRUE;
2727
2728         if (cfg->gshared) {
2729                 MonoInst *inst;
2730                 MonoGenericJitInfo *gi;
2731                 GSList *loclist = NULL;
2732
2733                 gi = mono_jit_info_get_generic_jit_info (jinfo);
2734                 g_assert (gi);
2735
2736                 if (cfg->method->dynamic)
2737                         gi->generic_sharing_context = g_new0 (MonoGenericSharingContext, 1);
2738                 else
2739                         gi->generic_sharing_context = (MonoGenericSharingContext *)mono_domain_alloc0 (cfg->domain, sizeof (MonoGenericSharingContext));
2740                 mini_init_gsctx (cfg->method->dynamic ? NULL : cfg->domain, NULL, cfg->gsctx_context, gi->generic_sharing_context);
2741
2742                 if ((method_to_compile->flags & METHOD_ATTRIBUTE_STATIC) ||
2743                                 mini_method_get_context (method_to_compile)->method_inst ||
2744                                 method_to_compile->klass->valuetype) {
2745                         g_assert (cfg->rgctx_var);
2746                 }
2747
2748                 gi->has_this = 1;
2749
2750                 if ((method_to_compile->flags & METHOD_ATTRIBUTE_STATIC) ||
2751                                 mini_method_get_context (method_to_compile)->method_inst ||
2752                                 method_to_compile->klass->valuetype) {
2753                         inst = cfg->rgctx_var;
2754                         if (!COMPILE_LLVM (cfg))
2755                                 g_assert (inst->opcode == OP_REGOFFSET);
2756                         loclist = cfg->rgctx_loclist;
2757                 } else {
2758                         inst = cfg->args [0];
2759                         loclist = cfg->this_loclist;
2760                 }
2761
2762                 if (loclist) {
2763                         /* Needed to handle async exceptions */
2764                         GSList *l;
2765                         int i;
2766
2767                         gi->nlocs = g_slist_length (loclist);
2768                         if (cfg->method->dynamic)
2769                                 gi->locations = (MonoDwarfLocListEntry *)g_malloc0 (gi->nlocs * sizeof (MonoDwarfLocListEntry));
2770                         else
2771                                 gi->locations = (MonoDwarfLocListEntry *)mono_domain_alloc0 (cfg->domain, gi->nlocs * sizeof (MonoDwarfLocListEntry));
2772                         i = 0;
2773                         for (l = loclist; l; l = l->next) {
2774                                 memcpy (&(gi->locations [i]), l->data, sizeof (MonoDwarfLocListEntry));
2775                                 i ++;
2776                         }
2777                 }
2778
2779                 if (COMPILE_LLVM (cfg)) {
2780                         g_assert (cfg->llvm_this_reg != -1);
2781                         gi->this_in_reg = 0;
2782                         gi->this_reg = cfg->llvm_this_reg;
2783                         gi->this_offset = cfg->llvm_this_offset;
2784                 } else if (inst->opcode == OP_REGVAR) {
2785                         gi->this_in_reg = 1;
2786                         gi->this_reg = inst->dreg;
2787                 } else {
2788                         g_assert (inst->opcode == OP_REGOFFSET);
2789 #ifdef TARGET_X86
2790                         g_assert (inst->inst_basereg == X86_EBP);
2791 #elif defined(TARGET_AMD64)
2792                         g_assert (inst->inst_basereg == X86_EBP || inst->inst_basereg == X86_ESP);
2793 #endif
2794                         g_assert (inst->inst_offset >= G_MININT32 && inst->inst_offset <= G_MAXINT32);
2795
2796                         gi->this_in_reg = 0;
2797                         gi->this_reg = inst->inst_basereg;
2798                         gi->this_offset = inst->inst_offset;
2799                 }
2800         }
2801
2802         if (num_holes) {
2803                 MonoTryBlockHoleTableJitInfo *table;
2804                 int i;
2805
2806                 table = mono_jit_info_get_try_block_hole_table_info (jinfo);
2807                 table->num_holes = (guint16)num_holes;
2808                 i = 0;
2809                 for (tmp = cfg->try_block_holes; tmp; tmp = tmp->next) {
2810                         guint32 start_bb_offset;
2811                         MonoTryBlockHoleJitInfo *hole;
2812                         TryBlockHole *hole_data = (TryBlockHole *)tmp->data;
2813                         MonoExceptionClause *ec = hole_data->clause;
2814                         int hole_end = hole_data->basic_block->native_offset + hole_data->basic_block->native_length;
2815                         MonoBasicBlock *clause_last_bb = cfg->cil_offset_to_bb [ec->try_offset + ec->try_len];
2816                         g_assert (clause_last_bb);
2817
2818                         /* Holes at the end of a try region can be represented by simply reducing the size of the block itself.*/
2819                         if (clause_last_bb->native_offset == hole_end)
2820                                 continue;
2821
2822                         start_bb_offset = hole_data->start_offset - hole_data->basic_block->native_offset;
2823                         hole = &table->holes [i++];
2824                         hole->clause = hole_data->clause - &header->clauses [0];
2825                         hole->offset = (guint32)hole_data->start_offset;
2826                         hole->length = (guint16)(hole_data->basic_block->native_length - start_bb_offset);
2827
2828                         if (G_UNLIKELY (cfg->verbose_level >= 4))
2829                                 printf ("\tTry block hole at eh clause %d offset %x length %x\n", hole->clause, hole->offset, hole->length);
2830                 }
2831                 g_assert (i == num_holes);
2832         }
2833
2834         if (jinfo->has_arch_eh_info) {
2835                 MonoArchEHJitInfo *info;
2836
2837                 info = mono_jit_info_get_arch_eh_info (jinfo);
2838
2839                 info->stack_size = stack_size;
2840         }
2841
2842         if (cfg->thunk_area) {
2843                 MonoThunkJitInfo *info;
2844
2845                 info = mono_jit_info_get_thunk_info (jinfo);
2846                 info->thunks_offset = cfg->thunks_offset;
2847                 info->thunks_size = cfg->thunk_area;
2848         }
2849
2850         if (COMPILE_LLVM (cfg)) {
2851                 if (num_clauses)
2852                         memcpy (&jinfo->clauses [0], &cfg->llvm_ex_info [0], num_clauses * sizeof (MonoJitExceptionInfo));
2853         } else if (header->num_clauses) {
2854                 int i;
2855
2856                 for (i = 0; i < header->num_clauses; i++) {
2857                         MonoExceptionClause *ec = &header->clauses [i];
2858                         MonoJitExceptionInfo *ei = &jinfo->clauses [i];
2859                         MonoBasicBlock *tblock;
2860                         MonoInst *exvar, *spvar;
2861
2862                         ei->flags = ec->flags;
2863
2864                         if (G_UNLIKELY (cfg->verbose_level >= 4))
2865                                 printf ("IL clause: try 0x%x-0x%x handler 0x%x-0x%x filter 0x%x\n", ec->try_offset, ec->try_offset + ec->try_len, ec->handler_offset, ec->handler_offset + ec->handler_len, ec->flags == MONO_EXCEPTION_CLAUSE_FILTER ? ec->data.filter_offset : 0);
2866
2867                         /*
2868                          * The spvars are needed by mono_arch_install_handler_block_guard ().
2869                          */
2870                         if (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
2871                                 int region;
2872
2873                                 region = ((i + 1) << 8) | MONO_REGION_FINALLY | ec->flags;
2874                                 spvar = mono_find_spvar_for_region (cfg, region);
2875                                 g_assert (spvar);
2876                                 ei->exvar_offset = spvar->inst_offset;
2877                         } else {
2878                                 exvar = mono_find_exvar_for_offset (cfg, ec->handler_offset);
2879                                 ei->exvar_offset = exvar ? exvar->inst_offset : 0;
2880                         }
2881
2882                         if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
2883                                 tblock = cfg->cil_offset_to_bb [ec->data.filter_offset];
2884                                 g_assert (tblock);
2885                                 ei->data.filter = cfg->native_code + tblock->native_offset;
2886                         } else {
2887                                 ei->data.catch_class = ec->data.catch_class;
2888                         }
2889
2890                         tblock = cfg->cil_offset_to_bb [ec->try_offset];
2891                         g_assert (tblock);
2892                         g_assert (tblock->native_offset);
2893                         ei->try_start = cfg->native_code + tblock->native_offset;
2894                         if (tblock->extend_try_block) {
2895                                 /*
2896                                  * Extend the try block backwards to include parts of the previous call
2897                                  * instruction.
2898                                  */
2899                                 ei->try_start = (guint8*)ei->try_start - cfg->backend->monitor_enter_adjustment;
2900                         }
2901                         if (ec->try_offset + ec->try_len < header->code_size)
2902                                 tblock = cfg->cil_offset_to_bb [ec->try_offset + ec->try_len];
2903                         else
2904                                 tblock = cfg->bb_exit;
2905                         if (G_UNLIKELY (cfg->verbose_level >= 4))
2906                                 printf ("looking for end of try [%d, %d] -> %p (code size %d)\n", ec->try_offset, ec->try_len, tblock, header->code_size);
2907                         g_assert (tblock);
2908                         if (!tblock->native_offset) {
2909                                 int j, end;
2910                                 for (j = ec->try_offset + ec->try_len, end = ec->try_offset; j >= end; --j) {
2911                                         MonoBasicBlock *bb = cfg->cil_offset_to_bb [j];
2912                                         if (bb && bb->native_offset) {
2913                                                 tblock = bb;
2914                                                 break;
2915                                         }
2916                                 }
2917                         }
2918                         ei->try_end = cfg->native_code + tblock->native_offset;
2919                         g_assert (tblock->native_offset);
2920                         tblock = cfg->cil_offset_to_bb [ec->handler_offset];
2921                         g_assert (tblock);
2922                         ei->handler_start = cfg->native_code + tblock->native_offset;
2923
2924                         for (tmp = cfg->try_block_holes; tmp; tmp = tmp->next) {
2925                                 TryBlockHole *hole = (TryBlockHole *)tmp->data;
2926                                 gpointer hole_end = cfg->native_code + (hole->basic_block->native_offset + hole->basic_block->native_length);
2927                                 if (hole->clause == ec && hole_end == ei->try_end) {
2928                                         if (G_UNLIKELY (cfg->verbose_level >= 4))
2929                                                 printf ("\tShortening try block %d from %x to %x\n", i, (int)((guint8*)ei->try_end - cfg->native_code), hole->start_offset);
2930
2931                                         ei->try_end = cfg->native_code + hole->start_offset;
2932                                         break;
2933                                 }
2934                         }
2935
2936                         if (ec->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
2937                                 int end_offset;
2938                                 if (ec->handler_offset + ec->handler_len < header->code_size) {
2939                                         tblock = cfg->cil_offset_to_bb [ec->handler_offset + ec->handler_len];
2940                                         if (tblock->native_offset) {
2941                                                 end_offset = tblock->native_offset;
2942                                         } else {
2943                                                 int j, end;
2944
2945                                                 for (j = ec->handler_offset + ec->handler_len, end = ec->handler_offset; j >= end; --j) {
2946                                                         MonoBasicBlock *bb = cfg->cil_offset_to_bb [j];
2947                                                         if (bb && bb->native_offset) {
2948                                                                 tblock = bb;
2949                                                                 break;
2950                                                         }
2951                                                 }
2952                                                 end_offset = tblock->native_offset +  tblock->native_length;
2953                                         }
2954                                 } else {
2955                                         end_offset = cfg->epilog_begin;
2956                                 }
2957                                 ei->data.handler_end = cfg->native_code + end_offset;
2958                         }
2959                 }
2960         }
2961
2962         if (G_UNLIKELY (cfg->verbose_level >= 4)) {
2963                 int i;
2964                 for (i = 0; i < jinfo->num_clauses; i++) {
2965                         MonoJitExceptionInfo *ei = &jinfo->clauses [i];
2966                         int start = (guint8*)ei->try_start - cfg->native_code;
2967                         int end = (guint8*)ei->try_end - cfg->native_code;
2968                         int handler = (guint8*)ei->handler_start - cfg->native_code;
2969                         int handler_end = (guint8*)ei->data.handler_end - cfg->native_code;
2970
2971                         printf ("JitInfo EH clause %d flags %x try %x-%x handler %x-%x\n", i, ei->flags, start, end, handler, handler_end);
2972                 }
2973         }
2974
2975         if (cfg->encoded_unwind_ops) {
2976                 /* Generated by LLVM */
2977                 jinfo->unwind_info = mono_cache_unwind_info (cfg->encoded_unwind_ops, cfg->encoded_unwind_ops_len);
2978                 g_free (cfg->encoded_unwind_ops);
2979         } else if (cfg->unwind_ops) {
2980                 guint32 info_len;
2981                 guint8 *unwind_info = mono_unwind_ops_encode (cfg->unwind_ops, &info_len);
2982                 guint32 unwind_desc;
2983
2984                 unwind_desc = mono_cache_unwind_info (unwind_info, info_len);
2985
2986                 if (cfg->has_unwind_info_for_epilog) {
2987                         MonoArchEHJitInfo *info;
2988
2989                         info = mono_jit_info_get_arch_eh_info (jinfo);
2990                         g_assert (info);
2991                         info->epilog_size = cfg->code_len - cfg->epilog_begin;
2992                 }
2993                 jinfo->unwind_info = unwind_desc;
2994                 g_free (unwind_info);
2995         } else {
2996                 jinfo->unwind_info = cfg->used_int_regs;
2997         }
2998
2999         return jinfo;
3000 }
3001
3002 /* Return whenever METHOD is a gsharedvt method */
3003 static gboolean
3004 is_gsharedvt_method (MonoMethod *method)
3005 {
3006         MonoGenericContext *context;
3007         MonoGenericInst *inst;
3008         int i;
3009
3010         if (!method->is_inflated)
3011                 return FALSE;
3012         context = mono_method_get_context (method);
3013         inst = context->class_inst;
3014         if (inst) {
3015                 for (i = 0; i < inst->type_argc; ++i)
3016                         if (mini_is_gsharedvt_gparam (inst->type_argv [i]))
3017                                 return TRUE;
3018         }
3019         inst = context->method_inst;
3020         if (inst) {
3021                 for (i = 0; i < inst->type_argc; ++i)
3022                         if (mini_is_gsharedvt_gparam (inst->type_argv [i]))
3023                                 return TRUE;
3024         }
3025         return FALSE;
3026 }
3027
3028 static gboolean
3029 is_open_method (MonoMethod *method)
3030 {
3031         MonoGenericContext *context;
3032
3033         if (!method->is_inflated)
3034                 return FALSE;
3035         context = mono_method_get_context (method);
3036         if (context->class_inst && context->class_inst->is_open)
3037                 return TRUE;
3038         if (context->method_inst && context->method_inst->is_open)
3039                 return TRUE;
3040         return FALSE;
3041 }
3042
3043 static void
3044 mono_create_gc_safepoint (MonoCompile *cfg, MonoBasicBlock *bblock)
3045 {
3046         MonoInst *poll_addr, *ins;
3047
3048         if (cfg->disable_gc_safe_points)
3049                 return;
3050
3051         if (cfg->verbose_level > 1)
3052                 printf ("ADDING SAFE POINT TO BB %d\n", bblock->block_num);
3053
3054 #if defined(__native_client_codegen__)
3055         NEW_AOTCONST (cfg, poll_addr, MONO_PATCH_INFO_GC_SAFE_POINT_FLAG, (gpointer)&__nacl_thread_suspension_needed);
3056 #else
3057         g_assert (mono_threads_is_coop_enabled ());
3058         NEW_AOTCONST (cfg, poll_addr, MONO_PATCH_INFO_GC_SAFE_POINT_FLAG, (gpointer)&mono_polling_required);
3059 #endif
3060
3061         MONO_INST_NEW (cfg, ins, OP_GC_SAFE_POINT);
3062         ins->sreg1 = poll_addr->dreg;
3063
3064          if (bblock->flags & BB_EXCEPTION_HANDLER) {
3065                 MonoInst *eh_op = bblock->code;
3066
3067                 if (eh_op && eh_op->opcode != OP_START_HANDLER && eh_op->opcode != OP_GET_EX_OBJ) {
3068                         eh_op = NULL;
3069                 } else {
3070                         MonoInst *next_eh_op = eh_op ? eh_op->next : NULL;
3071                         // skip all EH relateds ops
3072                         while (next_eh_op && (next_eh_op->opcode == OP_START_HANDLER || next_eh_op->opcode == OP_GET_EX_OBJ)) {
3073                                 eh_op = next_eh_op;
3074                                 next_eh_op = eh_op->next;
3075                         }
3076                 }
3077
3078                 mono_bblock_insert_after_ins (bblock, eh_op, poll_addr);
3079                 mono_bblock_insert_after_ins (bblock, poll_addr, ins);
3080         } else if (bblock == cfg->bb_entry) {
3081                 mono_bblock_insert_after_ins (bblock, bblock->last_ins, poll_addr);
3082                 mono_bblock_insert_after_ins (bblock, poll_addr, ins);
3083
3084         } else {
3085                 mono_bblock_insert_before_ins (bblock, NULL, poll_addr);
3086                 mono_bblock_insert_after_ins (bblock, poll_addr, ins);
3087         }
3088 }
3089
3090 /*
3091 This code inserts safepoints into managed code at important code paths.
3092 Those are:
3093
3094 -the first basic block
3095 -landing BB for exception handlers
3096 -loop body starts.
3097
3098 */
3099 static void
3100 mono_insert_safepoints (MonoCompile *cfg)
3101 {
3102         MonoBasicBlock *bb;
3103
3104 #if !defined(__native_client_codegen__)
3105         if (!mono_threads_is_coop_enabled ())
3106                 return;
3107 #endif
3108
3109         if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
3110                 WrapperInfo *info = mono_marshal_get_wrapper_info (cfg->method);
3111 #if defined(__native_client__) || defined(__native_client_codegen__)
3112                 gpointer poll_func = &mono_nacl_gc;
3113 #else
3114                 g_assert (mono_threads_is_coop_enabled ());
3115                 gpointer poll_func = &mono_threads_state_poll;
3116 #endif
3117
3118                 if (info && info->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER && info->d.icall.func == poll_func) {
3119                         if (cfg->verbose_level > 1)
3120                                 printf ("SKIPPING SAFEPOINTS for the polling function icall\n");
3121                         return;
3122                 }
3123         }
3124
3125         if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
3126                 if (cfg->verbose_level > 1)
3127                         printf ("SKIPPING SAFEPOINTS for native-to-managed wrappers.\n");
3128                 return;
3129         }
3130
3131         if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
3132                 WrapperInfo *info = mono_marshal_get_wrapper_info (cfg->method);
3133
3134                 if (info && info->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER &&
3135                         (info->d.icall.func == mono_thread_interruption_checkpoint ||
3136                         info->d.icall.func == mono_threads_exit_gc_safe_region_unbalanced)) {
3137                         /* These wrappers are called from the wrapper for the polling function, leading to potential stack overflow */
3138                         if (cfg->verbose_level > 1)
3139                                 printf ("SKIPPING SAFEPOINTS for wrapper %s\n", cfg->method->name);
3140                         return;
3141                 }
3142         }
3143
3144         if (cfg->verbose_level > 1)
3145                 printf ("INSERTING SAFEPOINTS\n");
3146         if (cfg->verbose_level > 2)
3147                 mono_print_code (cfg, "BEFORE SAFEPOINTS");
3148
3149         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
3150                 if (bb->loop_body_start || bb == cfg->bb_entry || bb->flags & BB_EXCEPTION_HANDLER)
3151                         mono_create_gc_safepoint (cfg, bb);
3152         }
3153
3154         if (cfg->verbose_level > 2)
3155                 mono_print_code (cfg, "AFTER SAFEPOINTS");
3156
3157 }
3158
3159
3160 static void
3161 mono_insert_branches_between_bblocks (MonoCompile *cfg)
3162 {
3163         MonoBasicBlock *bb;
3164
3165         /* Add branches between non-consecutive bblocks */
3166         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
3167                 if (bb->last_ins && MONO_IS_COND_BRANCH_OP (bb->last_ins) &&
3168                         bb->last_ins->inst_false_bb && bb->next_bb != bb->last_ins->inst_false_bb) {
3169                         /* we are careful when inverting, since bugs like #59580
3170                          * could show up when dealing with NaNs.
3171                          */
3172                         if (MONO_IS_COND_BRANCH_NOFP(bb->last_ins) && bb->next_bb == bb->last_ins->inst_true_bb) {
3173                                 MonoBasicBlock *tmp =  bb->last_ins->inst_true_bb;
3174                                 bb->last_ins->inst_true_bb = bb->last_ins->inst_false_bb;
3175                                 bb->last_ins->inst_false_bb = tmp;
3176
3177                                 bb->last_ins->opcode = mono_reverse_branch_op (bb->last_ins->opcode);
3178                         } else {
3179                                 MonoInst *inst = (MonoInst *)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst));
3180                                 inst->opcode = OP_BR;
3181                                 inst->inst_target_bb = bb->last_ins->inst_false_bb;
3182                                 mono_bblock_add_inst (bb, inst);
3183                         }
3184                 }
3185         }
3186
3187         if (cfg->verbose_level >= 4) {
3188                 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
3189                         MonoInst *tree = bb->code;
3190                         g_print ("DUMP BLOCK %d:\n", bb->block_num);
3191                         if (!tree)
3192                                 continue;
3193                         for (; tree; tree = tree->next) {
3194                                 mono_print_ins_index (-1, tree);
3195                         }
3196                 }
3197         }
3198
3199         /* FIXME: */
3200         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
3201                 bb->max_vreg = cfg->next_vreg;
3202         }
3203 }
3204
3205 static void
3206 init_backend (MonoBackend *backend)
3207 {
3208 #ifdef MONO_ARCH_NEED_GOT_VAR
3209         backend->need_got_var = 1;
3210 #endif
3211 #ifdef MONO_ARCH_HAVE_CARD_TABLE_WBARRIER
3212         backend->have_card_table_wb = 1;
3213 #endif
3214 #ifdef MONO_ARCH_HAVE_OP_GENERIC_CLASS_INIT
3215         backend->have_op_generic_class_init = 1;
3216 #endif
3217 #ifdef MONO_ARCH_EMULATE_MUL_DIV
3218         backend->emulate_mul_div = 1;
3219 #endif
3220 #ifdef MONO_ARCH_EMULATE_DIV
3221         backend->emulate_div = 1;
3222 #endif
3223 #if !defined(MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS)
3224         backend->emulate_long_shift_opts = 1;
3225 #endif
3226 #ifdef MONO_ARCH_HAVE_OBJC_GET_SELECTOR
3227         backend->have_objc_get_selector = 1;
3228 #endif
3229 #ifdef MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK
3230         backend->have_generalized_imt_thunk = 1;
3231 #endif
3232 #ifdef MONO_ARCH_GSHARED_SUPPORTED
3233         backend->gshared_supported = 1;
3234 #endif
3235         if (MONO_ARCH_HAVE_TLS_GET)
3236                 backend->have_tls_get = 1;
3237 #ifdef MONO_ARCH_HAVE_TLS_GET_REG
3238                 backend->have_tls_get_reg = 1;
3239 #endif
3240         if (MONO_ARCH_USE_FPSTACK)
3241                 backend->use_fpstack = 1;
3242 #ifdef MONO_ARCH_HAVE_LIVERANGE_OPS
3243         backend->have_liverange_ops = 1;
3244 #endif
3245 #ifdef MONO_ARCH_HAVE_OP_TAIL_CALL
3246         backend->have_op_tail_call = 1;
3247 #endif
3248 #ifndef MONO_ARCH_MONITOR_ENTER_ADJUSTMENT
3249         backend->monitor_enter_adjustment = 1;
3250 #else
3251         backend->monitor_enter_adjustment = MONO_ARCH_MONITOR_ENTER_ADJUSTMENT;
3252 #endif
3253 #if defined(__mono_ilp32__)
3254         backend->ilp32 = 1;
3255 #endif
3256 #ifdef MONO_ARCH_HAVE_DUMMY_INIT
3257         backend->have_dummy_init = 1;
3258 #endif
3259 #ifdef MONO_ARCH_NEED_DIV_CHECK
3260         backend->need_div_check = 1;
3261 #endif
3262 #ifdef NO_UNALIGNED_ACCESS
3263         backend->no_unaligned_access = 1;
3264 #endif
3265 #ifdef MONO_ARCH_DYN_CALL_PARAM_AREA
3266         backend->dyn_call_param_area = MONO_ARCH_DYN_CALL_PARAM_AREA;
3267 #endif
3268 }
3269
3270 /*
3271  * mini_method_compile:
3272  * @method: the method to compile
3273  * @opts: the optimization flags to use
3274  * @domain: the domain where the method will be compiled in
3275  * @flags: compilation flags
3276  * @parts: debug flag
3277  *
3278  * Returns: a MonoCompile* pointer. Caller must check the exception_type
3279  * field in the returned struct to see if compilation succeded.
3280  */
3281 MonoCompile*
3282 mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFlags flags, int parts, int aot_method_index)
3283 {
3284         MonoMethodHeader *header;
3285         MonoMethodSignature *sig;
3286         MonoError err;
3287         MonoCompile *cfg;
3288         int i, code_size_ratio;
3289         gboolean try_generic_shared, try_llvm = FALSE;
3290         MonoMethod *method_to_compile, *method_to_register;
3291         gboolean method_is_gshared = FALSE;
3292         gboolean run_cctors = (flags & JIT_FLAG_RUN_CCTORS) ? 1 : 0;
3293         gboolean compile_aot = (flags & JIT_FLAG_AOT) ? 1 : 0;
3294         gboolean full_aot = (flags & JIT_FLAG_FULL_AOT) ? 1 : 0;
3295         gboolean disable_direct_icalls = (flags & JIT_FLAG_NO_DIRECT_ICALLS) ? 1 : 0;
3296         gboolean gsharedvt_method = FALSE;
3297 #ifdef ENABLE_LLVM
3298         gboolean llvm = (flags & JIT_FLAG_LLVM) ? 1 : 0;
3299 #endif
3300         static gboolean verbose_method_inited;
3301         static const char *verbose_method_name;
3302
3303         InterlockedIncrement (&mono_jit_stats.methods_compiled);
3304         if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)
3305                 mono_profiler_method_jit (method);
3306         if (MONO_METHOD_COMPILE_BEGIN_ENABLED ())
3307                 MONO_PROBE_METHOD_COMPILE_BEGIN (method);
3308
3309         gsharedvt_method = is_gsharedvt_method (method);
3310
3311         /*
3312          * In AOT mode, method can be the following:
3313          * - a gsharedvt method.
3314          * - a method inflated with type parameters. This is for ref/partial sharing.
3315          * - a method inflated with concrete types.
3316          */
3317         if (compile_aot) {
3318                 if (is_open_method (method)) {
3319                         try_generic_shared = TRUE;
3320                         method_is_gshared = TRUE;
3321                 } else {
3322                         try_generic_shared = FALSE;
3323                 }
3324                 g_assert (opts & MONO_OPT_GSHARED);
3325         } else {
3326                 try_generic_shared = mono_class_generic_sharing_enabled (method->klass) &&
3327                         (opts & MONO_OPT_GSHARED) && mono_method_is_generic_sharable (method, FALSE);
3328                 if (mini_is_gsharedvt_sharable_method (method)) {
3329                         /*
3330                         if (!mono_debug_count ())
3331                                 try_generic_shared = FALSE;
3332                         */
3333                 }
3334         }
3335
3336         /*
3337         if (try_generic_shared && !mono_debug_count ())
3338                 try_generic_shared = FALSE;
3339         */
3340
3341         if (opts & MONO_OPT_GSHARED) {
3342                 if (try_generic_shared)
3343                         mono_stats.generics_sharable_methods++;
3344                 else if (mono_method_is_generic_impl (method))
3345                         mono_stats.generics_unsharable_methods++;
3346         }
3347
3348 #ifdef ENABLE_LLVM
3349         try_llvm = mono_use_llvm || llvm;
3350 #endif
3351
3352  restart_compile:
3353         if (method_is_gshared) {
3354                 method_to_compile = method;
3355         } else {
3356                 if (try_generic_shared) {
3357                         method_to_compile = mini_get_shared_method (method);
3358                         g_assert (method_to_compile);
3359                 } else {
3360                         method_to_compile = method;
3361                 }
3362         }
3363
3364         cfg = g_new0 (MonoCompile, 1);
3365         cfg->method = method_to_compile;
3366         cfg->mempool = mono_mempool_new ();
3367         cfg->opt = opts;
3368         cfg->prof_options = mono_profiler_get_events ();
3369         cfg->run_cctors = run_cctors;
3370         cfg->domain = domain;
3371         cfg->verbose_level = mini_verbose;
3372         cfg->compile_aot = compile_aot;
3373         cfg->full_aot = full_aot;
3374         cfg->disable_omit_fp = debug_options.disable_omit_fp;
3375         cfg->skip_visibility = method->skip_visibility;
3376         cfg->orig_method = method;
3377         cfg->gen_seq_points = debug_options.gen_seq_points_compact_data || debug_options.gen_sdb_seq_points;
3378         cfg->gen_sdb_seq_points = debug_options.gen_sdb_seq_points;
3379         cfg->llvm_only = (flags & JIT_FLAG_LLVM_ONLY) != 0;
3380         cfg->backend = current_backend;
3381
3382 #ifdef PLATFORM_ANDROID
3383         if (cfg->method->wrapper_type != MONO_WRAPPER_NONE) {
3384                 /* FIXME: Why is this needed */
3385                 cfg->gen_seq_points = FALSE;
3386                 cfg->gen_sdb_seq_points = FALSE;
3387         }
3388 #endif
3389         /* coop / nacl requires loop detection to happen */
3390 #if defined(__native_client_codegen__)
3391         cfg->opt |= MONO_OPT_LOOP;
3392 #else
3393         if (mono_threads_is_coop_enabled ())
3394                 cfg->opt |= MONO_OPT_LOOP;
3395 #endif
3396         cfg->explicit_null_checks = debug_options.explicit_null_checks || (flags & JIT_FLAG_EXPLICIT_NULL_CHECKS);
3397         cfg->soft_breakpoints = debug_options.soft_breakpoints;
3398         cfg->check_pinvoke_callconv = debug_options.check_pinvoke_callconv;
3399         cfg->disable_direct_icalls = disable_direct_icalls;
3400         if (try_generic_shared)
3401                 cfg->gshared = TRUE;
3402         cfg->compile_llvm = try_llvm;
3403         cfg->token_info_hash = g_hash_table_new (NULL, NULL);
3404         if (cfg->compile_aot)
3405                 cfg->method_index = aot_method_index;
3406
3407         /*
3408         if (!mono_debug_count ())
3409                 cfg->opt &= ~MONO_OPT_FLOAT32;
3410         */
3411         if (cfg->llvm_only)
3412                 cfg->opt &= ~MONO_OPT_SIMD;
3413         cfg->r4fp = (cfg->opt & MONO_OPT_FLOAT32) ? 1 : 0;
3414         cfg->r4_stack_type = cfg->r4fp ? STACK_R4 : STACK_R8;
3415
3416         if (cfg->gen_seq_points)
3417                 cfg->seq_points = g_ptr_array_new ();
3418         mono_error_init (&cfg->error);
3419
3420         if (cfg->compile_aot && !try_generic_shared && (method->is_generic || method->klass->generic_container || method_is_gshared)) {
3421                 cfg->exception_type = MONO_EXCEPTION_GENERIC_SHARING_FAILED;
3422                 return cfg;
3423         }
3424
3425         if (cfg->gshared && (gsharedvt_method || mini_is_gsharedvt_sharable_method (method))) {
3426                 MonoMethodInflated *inflated;
3427                 MonoGenericContext *context;
3428
3429                 if (gsharedvt_method) {
3430                         g_assert (method->is_inflated);
3431                         inflated = (MonoMethodInflated*)method;
3432                         context = &inflated->context;
3433
3434                         /* We are compiling a gsharedvt method directly */
3435                         g_assert (compile_aot);
3436                 } else {
3437                         g_assert (method_to_compile->is_inflated);
3438                         inflated = (MonoMethodInflated*)method_to_compile;
3439                         context = &inflated->context;
3440                 }
3441
3442                 mini_init_gsctx (NULL, cfg->mempool, context, &cfg->gsctx);
3443                 cfg->gsctx_context = context;
3444
3445                 cfg->gsharedvt = TRUE;
3446                 if (!cfg->llvm_only) {
3447                         cfg->disable_llvm = TRUE;
3448                         cfg->exception_message = g_strdup ("gsharedvt");
3449                 }
3450         }
3451
3452         if (cfg->gshared) {
3453                 method_to_register = method_to_compile;
3454         } else {
3455                 g_assert (method == method_to_compile);
3456                 method_to_register = method;
3457         }
3458         cfg->method_to_register = method_to_register;
3459
3460         mono_error_init (&err);
3461         sig = mono_method_signature_checked (cfg->method, &err);        
3462         if (!sig) {
3463                 cfg->exception_type = MONO_EXCEPTION_TYPE_LOAD;
3464                 cfg->exception_message = g_strdup (mono_error_get_message (&err));
3465                 mono_error_cleanup (&err);
3466                 if (MONO_METHOD_COMPILE_END_ENABLED ())
3467                         MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
3468                 return cfg;
3469         }
3470
3471         header = cfg->header = mono_method_get_header_checked (cfg->method, &cfg->error);
3472         if (!header) {
3473                 mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
3474                 if (MONO_METHOD_COMPILE_END_ENABLED ())
3475                         MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
3476                 return cfg;
3477         }
3478
3479 #ifdef ENABLE_LLVM
3480         {
3481                 static gboolean inited;
3482
3483                 if (!inited)
3484                         inited = TRUE;
3485
3486                 /* 
3487                  * Check for methods which cannot be compiled by LLVM early, to avoid
3488                  * the extra compilation pass.
3489                  */
3490                 if (COMPILE_LLVM (cfg)) {
3491                         mono_llvm_check_method_supported (cfg);
3492                         if (cfg->disable_llvm) {
3493                                 if (cfg->verbose_level >= (cfg->llvm_only ? 0 : 1)) {
3494                                         //nm = mono_method_full_name (cfg->method, TRUE);
3495                                         printf ("LLVM failed for '%s': %s\n", method->name, cfg->exception_message);
3496                                         //g_free (nm);
3497                                 }
3498                                 if (cfg->llvm_only) {
3499                                         cfg->disable_aot = TRUE;
3500                                         return cfg;
3501                                 }
3502                                 mono_destroy_compile (cfg);
3503                                 try_llvm = FALSE;
3504                                 goto restart_compile;
3505                         }
3506                 }
3507         }
3508 #endif
3509
3510         /* The debugger has no liveness information, so avoid sharing registers/stack slots */
3511         if (debug_options.mdb_optimizations) {
3512                 cfg->disable_reuse_registers = TRUE;
3513                 cfg->disable_reuse_stack_slots = TRUE;
3514                 /* 
3515                  * This decreases the change the debugger will read registers/stack slots which are
3516                  * not yet initialized.
3517                  */
3518                 cfg->disable_initlocals_opt = TRUE;
3519
3520                 cfg->extend_live_ranges = TRUE;
3521
3522                 /* The debugger needs all locals to be on the stack or in a global register */
3523                 cfg->disable_vreg_to_lvreg = TRUE;
3524
3525                 /* Don't remove unused variables when running inside the debugger since the user
3526                  * may still want to view them. */
3527                 cfg->disable_deadce_vars = TRUE;
3528
3529                 cfg->opt &= ~MONO_OPT_DEADCE;
3530                 cfg->opt &= ~MONO_OPT_INLINE;
3531                 cfg->opt &= ~MONO_OPT_COPYPROP;
3532                 cfg->opt &= ~MONO_OPT_CONSPROP;
3533
3534                 /* This is needed for the soft debugger, which doesn't like code after the epilog */
3535                 cfg->disable_out_of_line_bblocks = TRUE;
3536         }
3537
3538         if (mono_using_xdebug) {
3539                 /* 
3540                  * Make each variable use its own register/stack slot and extend 
3541                  * their liveness to cover the whole method, making them displayable
3542                  * in gdb even after they are dead.
3543                  */
3544                 cfg->disable_reuse_registers = TRUE;
3545                 cfg->disable_reuse_stack_slots = TRUE;
3546                 cfg->extend_live_ranges = TRUE;
3547                 cfg->compute_precise_live_ranges = TRUE;
3548         }
3549
3550         mini_gc_init_cfg (cfg);
3551
3552         if (method->wrapper_type == MONO_WRAPPER_UNKNOWN) {
3553                 WrapperInfo *info = mono_marshal_get_wrapper_info (method);
3554
3555                 /* These wrappers are using linkonce linkage, so they can't access GOT slots */
3556                 if ((info && (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG || info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_OUT_SIG))) {
3557                         cfg->disable_gc_safe_points = TRUE;
3558                         /* This is safe, these wrappers only store to the stack */
3559                         cfg->gen_write_barriers = FALSE;
3560                 }
3561         }
3562
3563         if (COMPILE_LLVM (cfg)) {
3564                 cfg->opt |= MONO_OPT_ABCREM;
3565         }
3566
3567         if (!verbose_method_inited) {
3568                 verbose_method_name = g_getenv ("MONO_VERBOSE_METHOD");
3569                 verbose_method_inited = TRUE;
3570         }
3571         if (verbose_method_name) {
3572                 const char *name = verbose_method_name;
3573
3574                 if ((strchr (name, '.') > name) || strchr (name, ':')) {
3575                         MonoMethodDesc *desc;
3576                         
3577                         desc = mono_method_desc_new (name, TRUE);
3578                         if (mono_method_desc_full_match (desc, cfg->method)) {
3579                                 cfg->verbose_level = 4;
3580                         }
3581                         mono_method_desc_free (desc);
3582                 } else {
3583                         if (strcmp (cfg->method->name, name) == 0)
3584                                 cfg->verbose_level = 4;
3585                 }
3586         }
3587
3588         cfg->intvars = (guint16 *)mono_mempool_alloc0 (cfg->mempool, sizeof (guint16) * STACK_MAX * header->max_stack);
3589
3590         if (cfg->verbose_level > 0) {
3591                 char *method_name;
3592
3593                 method_name = mono_method_get_full_name (method);
3594                 g_print ("converting %s%s%smethod %s\n", COMPILE_LLVM (cfg) ? "llvm " : "", cfg->gsharedvt ? "gsharedvt " : "", (cfg->gshared && !cfg->gsharedvt) ? "gshared " : "", method_name);
3595                 /*
3596                 if (COMPILE_LLVM (cfg))
3597                         g_print ("converting llvm method %s\n", method_name = mono_method_full_name (method, TRUE));
3598                 else if (cfg->gsharedvt)
3599                         g_print ("converting gsharedvt method %s\n", method_name = mono_method_full_name (method_to_compile, TRUE));
3600                 else if (cfg->gshared)
3601                         g_print ("converting shared method %s\n", method_name = mono_method_full_name (method_to_compile, TRUE));
3602                 else
3603                         g_print ("converting method %s\n", method_name = mono_method_full_name (method, TRUE));
3604                 */
3605                 g_free (method_name);
3606         }
3607
3608         if (cfg->opt & MONO_OPT_ABCREM)
3609                 cfg->opt |= MONO_OPT_SSA;
3610
3611         cfg->rs = mono_regstate_new ();
3612         cfg->next_vreg = cfg->rs->next_vreg;
3613
3614         /* FIXME: Fix SSA to handle branches inside bblocks */
3615         if (cfg->opt & MONO_OPT_SSA)
3616                 cfg->enable_extended_bblocks = FALSE;
3617
3618         /*
3619          * FIXME: This confuses liveness analysis because variables which are assigned after
3620          * a branch inside a bblock become part of the kill set, even though the assignment
3621          * might not get executed. This causes the optimize_initlocals pass to delete some
3622          * assignments which are needed.
3623          * Also, the mono_if_conversion pass needs to be modified to recognize the code
3624          * created by this.
3625          */
3626         //cfg->enable_extended_bblocks = TRUE;
3627
3628         /*We must verify the method before doing any IR generation as mono_compile_create_vars can assert.*/
3629         if (mono_compile_is_broken (cfg, cfg->method, TRUE)) {
3630                 if (mini_get_debug_options ()->break_on_unverified)
3631                         G_BREAKPOINT ();
3632                 return cfg;
3633         }
3634
3635         /*
3636          * create MonoInst* which represents arguments and local variables
3637          */
3638         mono_compile_create_vars (cfg);
3639
3640         mono_cfg_dump_create_context (cfg);
3641         mono_cfg_dump_begin_group (cfg);
3642
3643         MONO_TIME_TRACK (mono_jit_stats.jit_method_to_ir, i = mono_method_to_ir (cfg, method_to_compile, NULL, NULL, NULL, NULL, 0, FALSE));
3644         mono_cfg_dump_ir (cfg, "method-to-ir");
3645
3646         if (i < 0) {
3647                 if (try_generic_shared && cfg->exception_type == MONO_EXCEPTION_GENERIC_SHARING_FAILED) {
3648                         if (compile_aot) {
3649                                 if (MONO_METHOD_COMPILE_END_ENABLED ())
3650                                         MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
3651                                 return cfg;
3652                         }
3653                         mono_destroy_compile (cfg);
3654                         try_generic_shared = FALSE;
3655                         goto restart_compile;
3656                 }
3657                 g_assert (cfg->exception_type != MONO_EXCEPTION_GENERIC_SHARING_FAILED);
3658
3659                 if (MONO_METHOD_COMPILE_END_ENABLED ())
3660                         MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
3661                 /* cfg contains the details of the failure, so let the caller cleanup */
3662                 return cfg;
3663         }
3664
3665         cfg->stat_basic_blocks += cfg->num_bblocks;
3666
3667         if (COMPILE_LLVM (cfg)) {
3668                 MonoInst *ins;
3669
3670                 /* The IR has to be in SSA form for LLVM */
3671                 cfg->opt |= MONO_OPT_SSA;
3672
3673                 // FIXME:
3674                 if (cfg->ret) {
3675                         // Allow SSA on the result value
3676                         cfg->ret->flags &= ~MONO_INST_VOLATILE;
3677
3678                         // Add an explicit return instruction referencing the return value
3679                         MONO_INST_NEW (cfg, ins, OP_SETRET);
3680                         ins->sreg1 = cfg->ret->dreg;
3681
3682                         MONO_ADD_INS (cfg->bb_exit, ins);
3683                 }
3684
3685                 cfg->opt &= ~MONO_OPT_LINEARS;
3686
3687                 /* FIXME: */
3688                 cfg->opt &= ~MONO_OPT_BRANCH;
3689         }
3690
3691         /* todo: remove code when we have verified that the liveness for try/catch blocks
3692          * works perfectly 
3693          */
3694         /* 
3695          * Currently, this can't be commented out since exception blocks are not
3696          * processed during liveness analysis.
3697          * It is also needed, because otherwise the local optimization passes would
3698          * delete assignments in cases like this:
3699          * r1 <- 1
3700          * <something which throws>
3701          * r1 <- 2
3702          * This also allows SSA to be run on methods containing exception clauses, since
3703          * SSA will ignore variables marked VOLATILE.
3704          */
3705         MONO_TIME_TRACK (mono_jit_stats.jit_liveness_handle_exception_clauses, mono_liveness_handle_exception_clauses (cfg));
3706         mono_cfg_dump_ir (cfg, "liveness_handle_exception_clauses");
3707
3708         MONO_TIME_TRACK (mono_jit_stats.jit_handle_out_of_line_bblock, mono_handle_out_of_line_bblock (cfg));
3709         mono_cfg_dump_ir (cfg, "handle_out_of_line_bblock");
3710
3711         /*g_print ("numblocks = %d\n", cfg->num_bblocks);*/
3712
3713         if (!COMPILE_LLVM (cfg)) {
3714                 MONO_TIME_TRACK (mono_jit_stats.jit_decompose_long_opts, mono_decompose_long_opts (cfg));
3715                 mono_cfg_dump_ir (cfg, "decompose_long_opts");
3716         }
3717
3718         /* Should be done before branch opts */
3719         if (cfg->opt & (MONO_OPT_CONSPROP | MONO_OPT_COPYPROP)) {
3720                 MONO_TIME_TRACK (mono_jit_stats.jit_local_cprop, mono_local_cprop (cfg));
3721                 mono_cfg_dump_ir (cfg, "local_cprop");
3722         }
3723
3724         /*
3725          * Should be done after cprop which can do strength reduction on
3726          * some of these ops, after propagating immediates.
3727          */
3728         if (cfg->has_emulated_ops) {
3729                 MONO_TIME_TRACK (mono_jit_stats.jit_local_emulate_ops, mono_local_emulate_ops (cfg));
3730                 mono_cfg_dump_ir (cfg, "local_emulate_ops");
3731         }
3732
3733         if (cfg->opt & MONO_OPT_BRANCH) {
3734                 MONO_TIME_TRACK (mono_jit_stats.jit_optimize_branches, mono_optimize_branches (cfg));
3735                 mono_cfg_dump_ir (cfg, "optimize_branches");
3736         }
3737
3738         /* This must be done _before_ global reg alloc and _after_ decompose */
3739         MONO_TIME_TRACK (mono_jit_stats.jit_handle_global_vregs, mono_handle_global_vregs (cfg));
3740         mono_cfg_dump_ir (cfg, "handle_global_vregs");
3741         if (cfg->opt & MONO_OPT_DEADCE) {
3742                 MONO_TIME_TRACK (mono_jit_stats.jit_local_deadce, mono_local_deadce (cfg));
3743                 mono_cfg_dump_ir (cfg, "local_deadce");
3744         }
3745         if (cfg->opt & MONO_OPT_ALIAS_ANALYSIS) {
3746                 MONO_TIME_TRACK (mono_jit_stats.jit_local_alias_analysis, mono_local_alias_analysis (cfg));
3747                 mono_cfg_dump_ir (cfg, "local_alias_analysis");
3748         }
3749         /* Disable this for LLVM to make the IR easier to handle */
3750         if (!COMPILE_LLVM (cfg)) {
3751                 MONO_TIME_TRACK (mono_jit_stats.jit_if_conversion, mono_if_conversion (cfg));
3752                 mono_cfg_dump_ir (cfg, "if_conversion");
3753         }
3754
3755         mono_threads_safepoint ();
3756
3757         MONO_TIME_TRACK (mono_jit_stats.jit_bb_ordering, mono_bb_ordering (cfg));
3758         mono_cfg_dump_ir (cfg, "bb_ordering");
3759
3760         if (((cfg->num_varinfo > 2000) || (cfg->num_bblocks > 1000)) && !cfg->compile_aot) {
3761                 /* 
3762                  * we disable some optimizations if there are too many variables
3763                  * because JIT time may become too expensive. The actual number needs 
3764                  * to be tweaked and eventually the non-linear algorithms should be fixed.
3765                  */
3766                 cfg->opt &= ~ (MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP);
3767                 cfg->disable_ssa = TRUE;
3768         }
3769
3770         if (cfg->opt & MONO_OPT_LOOP) {
3771                 MONO_TIME_TRACK (mono_jit_stats.jit_compile_dominator_info, mono_compile_dominator_info (cfg, MONO_COMP_DOM | MONO_COMP_IDOM));
3772                 MONO_TIME_TRACK (mono_jit_stats.jit_compute_natural_loops, mono_compute_natural_loops (cfg));
3773         }
3774
3775         MONO_TIME_TRACK (mono_jit_stats.jit_insert_safepoints, mono_insert_safepoints (cfg));
3776         mono_cfg_dump_ir (cfg, "insert_safepoints");
3777
3778         /* after method_to_ir */
3779         if (parts == 1) {
3780                 if (MONO_METHOD_COMPILE_END_ENABLED ())
3781                         MONO_PROBE_METHOD_COMPILE_END (method, TRUE);
3782                 return cfg;
3783         }
3784
3785         /*
3786           if (header->num_clauses)
3787           cfg->disable_ssa = TRUE;
3788         */
3789
3790 //#define DEBUGSSA "logic_run"
3791 //#define DEBUGSSA_CLASS "Tests"
3792 #ifdef DEBUGSSA
3793
3794         if (!cfg->disable_ssa) {
3795                 mono_local_cprop (cfg);
3796
3797 #ifndef DISABLE_SSA
3798                 mono_ssa_compute (cfg);
3799 #endif
3800         }
3801 #else 
3802         if (cfg->opt & MONO_OPT_SSA) {
3803                 if (!(cfg->comp_done & MONO_COMP_SSA) && !cfg->disable_ssa) {
3804 #ifndef DISABLE_SSA
3805                         MONO_TIME_TRACK (mono_jit_stats.jit_ssa_compute, mono_ssa_compute (cfg));
3806                         mono_cfg_dump_ir (cfg, "ssa_compute");
3807 #endif
3808
3809                         if (cfg->verbose_level >= 2) {
3810                                 print_dfn (cfg);
3811                         }
3812                 }
3813         }
3814 #endif
3815
3816         /* after SSA translation */
3817         if (parts == 2) {
3818                 if (MONO_METHOD_COMPILE_END_ENABLED ())
3819                         MONO_PROBE_METHOD_COMPILE_END (method, TRUE);
3820                 return cfg;
3821         }
3822
3823         if ((cfg->opt & MONO_OPT_CONSPROP) || (cfg->opt & MONO_OPT_COPYPROP)) {
3824                 if (cfg->comp_done & MONO_COMP_SSA && !COMPILE_LLVM (cfg)) {
3825 #ifndef DISABLE_SSA
3826                         MONO_TIME_TRACK (mono_jit_stats.jit_ssa_cprop, mono_ssa_cprop (cfg));
3827                         mono_cfg_dump_ir (cfg, "ssa_cprop");
3828 #endif
3829                 }
3830         }
3831
3832 #ifndef DISABLE_SSA
3833         if (cfg->comp_done & MONO_COMP_SSA && !COMPILE_LLVM (cfg)) {
3834                 //mono_ssa_strength_reduction (cfg);
3835
3836                 if (cfg->opt & MONO_OPT_DEADCE) {
3837                         MONO_TIME_TRACK (mono_jit_stats.jit_ssa_deadce, mono_ssa_deadce (cfg));
3838                         mono_cfg_dump_ir (cfg, "ssa_deadce");
3839                 }
3840
3841                 if ((cfg->flags & (MONO_CFG_HAS_LDELEMA|MONO_CFG_HAS_CHECK_THIS)) && (cfg->opt & MONO_OPT_ABCREM)) {
3842                         MONO_TIME_TRACK (mono_jit_stats.jit_perform_abc_removal, mono_perform_abc_removal (cfg));
3843                         mono_cfg_dump_ir (cfg, "perform_abc_removal");
3844                 }
3845
3846                 MONO_TIME_TRACK (mono_jit_stats.jit_ssa_remove, mono_ssa_remove (cfg));
3847                 mono_cfg_dump_ir (cfg, "ssa_remove");
3848                 MONO_TIME_TRACK (mono_jit_stats.jit_local_cprop2, mono_local_cprop (cfg));
3849                 mono_cfg_dump_ir (cfg, "local_cprop2");
3850                 MONO_TIME_TRACK (mono_jit_stats.jit_handle_global_vregs2, mono_handle_global_vregs (cfg));
3851                 mono_cfg_dump_ir (cfg, "handle_global_vregs2");
3852                 if (cfg->opt & MONO_OPT_DEADCE) {
3853                         MONO_TIME_TRACK (mono_jit_stats.jit_local_deadce2, mono_local_deadce (cfg));
3854                         mono_cfg_dump_ir (cfg, "local_deadce2");
3855                 }
3856
3857                 if (cfg->opt & MONO_OPT_BRANCH) {
3858                         MONO_TIME_TRACK (mono_jit_stats.jit_optimize_branches2, mono_optimize_branches (cfg));
3859                         mono_cfg_dump_ir (cfg, "optimize_branches2");
3860                 }
3861         }
3862 #endif
3863
3864         if (cfg->comp_done & MONO_COMP_SSA && COMPILE_LLVM (cfg)) {
3865                 mono_ssa_loop_invariant_code_motion (cfg);
3866                 mono_cfg_dump_ir (cfg, "loop_invariant_code_motion");
3867                 /* This removes MONO_INST_FAULT flags too so perform it unconditionally */
3868                 if (cfg->opt & MONO_OPT_ABCREM) {
3869                         mono_perform_abc_removal (cfg);
3870                         mono_cfg_dump_ir (cfg, "abc_removal");
3871                 }
3872         }
3873
3874         /* after SSA removal */
3875         if (parts == 3) {
3876                 if (MONO_METHOD_COMPILE_END_ENABLED ())
3877                         MONO_PROBE_METHOD_COMPILE_END (method, TRUE);
3878                 return cfg;
3879         }
3880
3881         if (cfg->llvm_only && cfg->gsharedvt)
3882                 mono_ssa_remove_gsharedvt (cfg);
3883
3884 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
3885         if (COMPILE_SOFT_FLOAT (cfg))
3886                 mono_decompose_soft_float (cfg);
3887 #endif
3888         MONO_TIME_TRACK (mono_jit_stats.jit_decompose_vtype_opts, mono_decompose_vtype_opts (cfg));
3889         if (cfg->flags & MONO_CFG_HAS_ARRAY_ACCESS) {
3890                 MONO_TIME_TRACK (mono_jit_stats.jit_decompose_array_access_opts, mono_decompose_array_access_opts (cfg));
3891                 mono_cfg_dump_ir (cfg, "decompose_array_access_opts");
3892         }
3893
3894         if (cfg->got_var) {
3895 #ifndef MONO_ARCH_GOT_REG
3896                 GList *regs;
3897 #endif
3898                 int got_reg;
3899
3900                 g_assert (cfg->got_var_allocated);
3901
3902                 /* 
3903                  * Allways allocate the GOT var to a register, because keeping it
3904                  * in memory will increase the number of live temporaries in some
3905                  * code created by inssel.brg, leading to the well known spills+
3906                  * branches problem. Testcase: mcs crash in 
3907                  * System.MonoCustomAttrs:GetCustomAttributes.
3908                  */
3909 #ifdef MONO_ARCH_GOT_REG
3910                 got_reg = MONO_ARCH_GOT_REG;
3911 #else
3912                 regs = mono_arch_get_global_int_regs (cfg);
3913                 g_assert (regs);
3914                 got_reg = GPOINTER_TO_INT (regs->data);
3915                 g_list_free (regs);
3916 #endif
3917                 cfg->got_var->opcode = OP_REGVAR;
3918                 cfg->got_var->dreg = got_reg;
3919                 cfg->used_int_regs |= 1LL << cfg->got_var->dreg;
3920         }
3921
3922         /*
3923          * Have to call this again to process variables added since the first call.
3924          */
3925         MONO_TIME_TRACK(mono_jit_stats.jit_liveness_handle_exception_clauses2, mono_liveness_handle_exception_clauses (cfg));
3926
3927         if (cfg->opt & MONO_OPT_LINEARS) {
3928                 GList *vars, *regs, *l;
3929                 
3930                 /* fixme: maybe we can avoid to compute livenesss here if already computed ? */
3931                 cfg->comp_done &= ~MONO_COMP_LIVENESS;
3932                 if (!(cfg->comp_done & MONO_COMP_LIVENESS))
3933                         MONO_TIME_TRACK (mono_jit_stats.jit_analyze_liveness, mono_analyze_liveness (cfg));
3934
3935                 if ((vars = mono_arch_get_allocatable_int_vars (cfg))) {
3936                         regs = mono_arch_get_global_int_regs (cfg);
3937                         /* Remove the reg reserved for holding the GOT address */
3938                         if (cfg->got_var) {
3939                                 for (l = regs; l; l = l->next) {
3940                                         if (GPOINTER_TO_UINT (l->data) == cfg->got_var->dreg) {
3941                                                 regs = g_list_delete_link (regs, l);
3942                                                 break;
3943                                         }
3944                                 }
3945                         }
3946                         MONO_TIME_TRACK (mono_jit_stats.jit_linear_scan, mono_linear_scan (cfg, vars, regs, &cfg->used_int_regs));
3947                         mono_cfg_dump_ir (cfg, "linear_scan");
3948                 }
3949         }
3950
3951         //mono_print_code (cfg, "");
3952
3953     //print_dfn (cfg);
3954         
3955         /* variables are allocated after decompose, since decompose could create temps */
3956         if (!COMPILE_LLVM (cfg)) {
3957                 MONO_TIME_TRACK (mono_jit_stats.jit_arch_allocate_vars, mono_arch_allocate_vars (cfg));
3958                 mono_cfg_dump_ir (cfg, "arch_allocate_vars");
3959                 if (cfg->exception_type)
3960                         return cfg;
3961         }
3962
3963         if (cfg->gsharedvt)
3964                 mono_allocate_gsharedvt_vars (cfg);
3965
3966         if (!COMPILE_LLVM (cfg)) {
3967                 gboolean need_local_opts;
3968                 MONO_TIME_TRACK (mono_jit_stats.jit_spill_global_vars, mono_spill_global_vars (cfg, &need_local_opts));
3969                 mono_cfg_dump_ir (cfg, "spill_global_vars");
3970
3971                 if (need_local_opts || cfg->compile_aot) {
3972                         /* To optimize code created by spill_global_vars */
3973                         MONO_TIME_TRACK (mono_jit_stats.jit_local_cprop3, mono_local_cprop (cfg));
3974                         if (cfg->opt & MONO_OPT_DEADCE)
3975                                 MONO_TIME_TRACK (mono_jit_stats.jit_local_deadce3, mono_local_deadce (cfg));
3976                         mono_cfg_dump_ir (cfg, "needs_local_opts");
3977                 }
3978         }
3979
3980         mono_insert_branches_between_bblocks (cfg);
3981
3982         if (COMPILE_LLVM (cfg)) {
3983 #ifdef ENABLE_LLVM
3984                 char *nm;
3985
3986                 /* The IR has to be in SSA form for LLVM */
3987                 if (!(cfg->comp_done & MONO_COMP_SSA)) {
3988                         cfg->exception_message = g_strdup ("SSA disabled.");
3989                         cfg->disable_llvm = TRUE;
3990                 }
3991
3992                 if (cfg->flags & MONO_CFG_HAS_ARRAY_ACCESS)
3993                         mono_decompose_array_access_opts (cfg);
3994
3995                 if (!cfg->disable_llvm)
3996                         mono_llvm_emit_method (cfg);
3997                 if (cfg->disable_llvm) {
3998                         if (cfg->verbose_level >= (cfg->llvm_only ? 0 : 1)) {
3999                                 //nm = mono_method_full_name (cfg->method, TRUE);
4000                                 printf ("LLVM failed for '%s': %s\n", method->name, cfg->exception_message);
4001                                 //g_free (nm);
4002                         }
4003                         if (cfg->llvm_only) {
4004                                 cfg->disable_aot = TRUE;
4005                                 return cfg;
4006                         }
4007                         mono_destroy_compile (cfg);
4008                         try_llvm = FALSE;
4009                         goto restart_compile;
4010                 }
4011
4012                 if (cfg->verbose_level > 0 && !cfg->compile_aot) {
4013                         nm = mono_method_full_name (cfg->method, TRUE);
4014                         g_print ("LLVM Method %s emitted at %p to %p (code length %d) [%s]\n", 
4015                                          nm, 
4016                                          cfg->native_code, cfg->native_code + cfg->code_len, cfg->code_len, cfg->domain->friendly_name);
4017                         g_free (nm);
4018                 }
4019 #endif
4020         } else {
4021                 MONO_TIME_TRACK (mono_jit_stats.jit_codegen, mono_codegen (cfg));
4022                 mono_cfg_dump_ir (cfg, "codegen");
4023                 if (cfg->exception_type)
4024                         return cfg;
4025         }
4026
4027         if (COMPILE_LLVM (cfg))
4028                 InterlockedIncrement (&mono_jit_stats.methods_with_llvm);
4029         else
4030                 InterlockedIncrement (&mono_jit_stats.methods_without_llvm);
4031
4032         MONO_TIME_TRACK (mono_jit_stats.jit_create_jit_info, cfg->jit_info = create_jit_info (cfg, method_to_compile));
4033
4034 #ifdef MONO_ARCH_HAVE_LIVERANGE_OPS
4035         if (cfg->extend_live_ranges) {
4036                 /* Extend live ranges to cover the whole method */
4037                 for (i = 0; i < cfg->num_varinfo; ++i)
4038                         MONO_VARINFO (cfg, i)->live_range_end = cfg->code_len;
4039         }
4040 #endif
4041
4042         if (!cfg->compile_aot)
4043                 mono_save_xdebug_info (cfg);
4044
4045         MONO_TIME_TRACK (mono_jit_stats.jit_gc_create_gc_map, mini_gc_create_gc_map (cfg));
4046  
4047         MONO_TIME_TRACK (mono_jit_stats.jit_save_seq_point_info, mono_save_seq_point_info (cfg));
4048
4049         if (cfg->verbose_level >= 2) {
4050                 char *id =  mono_method_full_name (cfg->method, FALSE);
4051                 mono_disassemble_code (cfg, cfg->native_code, cfg->code_len, id + 3);
4052                 g_free (id);
4053         }
4054
4055         if (!cfg->compile_aot) {
4056                 mono_domain_lock (cfg->domain);
4057                 mono_jit_info_table_add (cfg->domain, cfg->jit_info);
4058
4059                 if (cfg->method->dynamic)
4060                         mono_dynamic_code_hash_lookup (cfg->domain, cfg->method)->ji = cfg->jit_info;
4061                 mono_domain_unlock (cfg->domain);
4062         }
4063
4064 #if 0
4065         if (cfg->gsharedvt)
4066                 printf ("GSHAREDVT: %s\n", mono_method_full_name (cfg->method, TRUE));
4067 #endif
4068
4069         /* collect statistics */
4070 #ifndef DISABLE_PERFCOUNTERS
4071         mono_perfcounters->jit_methods++;
4072         mono_perfcounters->jit_bytes += header->code_size;
4073 #endif
4074         mono_jit_stats.allocated_code_size += cfg->code_len;
4075         code_size_ratio = cfg->code_len;
4076         if (code_size_ratio > mono_jit_stats.biggest_method_size && mono_jit_stats.enabled) {
4077                 mono_jit_stats.biggest_method_size = code_size_ratio;
4078                 g_free (mono_jit_stats.biggest_method);
4079                 mono_jit_stats.biggest_method = g_strdup_printf ("%s::%s)", method->klass->name, method->name);
4080         }
4081         code_size_ratio = (code_size_ratio * 100) / header->code_size;
4082         if (code_size_ratio > mono_jit_stats.max_code_size_ratio && mono_jit_stats.enabled) {
4083                 mono_jit_stats.max_code_size_ratio = code_size_ratio;
4084                 g_free (mono_jit_stats.max_ratio_method);
4085                 mono_jit_stats.max_ratio_method = g_strdup_printf ("%s::%s)", method->klass->name, method->name);
4086         }
4087         mono_jit_stats.native_code_size += cfg->code_len;
4088
4089         if (MONO_METHOD_COMPILE_END_ENABLED ())
4090                 MONO_PROBE_METHOD_COMPILE_END (method, TRUE);
4091
4092         mono_cfg_dump_close_group (cfg);
4093
4094         return cfg;
4095 }
4096
4097 void*
4098 mono_arch_instrument_epilog (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments)
4099 {
4100         return mono_arch_instrument_epilog_full (cfg, func, p, enable_arguments, FALSE);
4101 }
4102
4103 void
4104 mono_cfg_add_try_hole (MonoCompile *cfg, MonoExceptionClause *clause, guint8 *start, MonoBasicBlock *bb)
4105 {
4106         TryBlockHole *hole = (TryBlockHole *)mono_mempool_alloc (cfg->mempool, sizeof (TryBlockHole));
4107         hole->clause = clause;
4108         hole->start_offset = start - cfg->native_code;
4109         hole->basic_block = bb;
4110
4111         cfg->try_block_holes = g_slist_append_mempool (cfg->mempool, cfg->try_block_holes, hole);
4112 }
4113
4114 void
4115 mono_cfg_set_exception (MonoCompile *cfg, int type)
4116 {
4117         cfg->exception_type = type;
4118 }
4119
4120 /* Assumes ownership of the MSG argument */
4121 void
4122 mono_cfg_set_exception_invalid_program (MonoCompile *cfg, char *msg)
4123 {
4124         mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
4125         mono_error_set_generic_error (&cfg->error, "System", "InvalidProgramException", msg);
4126 }
4127
4128 #endif /* DISABLE_JIT */
4129
4130 static MonoJitInfo*
4131 create_jit_info_for_trampoline (MonoMethod *wrapper, MonoTrampInfo *info)
4132 {
4133         MonoDomain *domain = mono_get_root_domain ();
4134         MonoJitInfo *jinfo;
4135         guint8 *uw_info;
4136         guint32 info_len;
4137
4138         if (info->uw_info) {
4139                 uw_info = info->uw_info;
4140                 info_len = info->uw_info_len;
4141         } else {
4142                 uw_info = mono_unwind_ops_encode (info->unwind_ops, &info_len);
4143         }
4144
4145         jinfo = (MonoJitInfo *)mono_domain_alloc0 (domain, MONO_SIZEOF_JIT_INFO);
4146         jinfo->d.method = wrapper;
4147         jinfo->code_start = info->code;
4148         jinfo->code_size = info->code_size;
4149         jinfo->unwind_info = mono_cache_unwind_info (uw_info, info_len);
4150
4151         if (!info->uw_info)
4152                 g_free (uw_info);
4153
4154         return jinfo;
4155 }
4156
4157 GTimer *mono_time_track_start ()
4158 {
4159         return g_timer_new ();
4160 }
4161
4162 void mono_time_track_end (double *time, GTimer *timer)
4163 {
4164         g_timer_stop (timer);
4165         *time += g_timer_elapsed (timer, NULL);
4166         g_timer_destroy (timer);
4167 }
4168
4169 void mono_update_jit_stats (MonoCompile *cfg)
4170 {
4171         mono_jit_stats.allocate_var += cfg->stat_allocate_var;
4172         mono_jit_stats.locals_stack_size += cfg->stat_locals_stack_size;
4173         mono_jit_stats.basic_blocks += cfg->stat_basic_blocks;
4174         mono_jit_stats.max_basic_blocks = MAX (cfg->stat_basic_blocks, mono_jit_stats.max_basic_blocks);
4175         mono_jit_stats.cil_code_size += cfg->stat_cil_code_size;
4176         mono_jit_stats.regvars += cfg->stat_n_regvars;
4177         mono_jit_stats.inlineable_methods += cfg->stat_inlineable_methods;
4178         mono_jit_stats.inlined_methods += cfg->stat_inlined_methods;
4179         mono_jit_stats.code_reallocs += cfg->stat_code_reallocs;
4180 }
4181
4182 /*
4183  * mono_jit_compile_method_inner:
4184  *
4185  *   Main entry point for the JIT.
4186  */
4187 gpointer
4188 mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, int opt, MonoError *error)
4189 {
4190         MonoCompile *cfg;
4191         gpointer code = NULL;
4192         MonoJitInfo *jinfo, *info;
4193         MonoVTable *vtable;
4194         MonoException *ex = NULL;
4195         guint32 prof_options;
4196         GTimer *jit_timer;
4197         MonoMethod *prof_method, *shared;
4198
4199         mono_error_init (error);
4200
4201         if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
4202             (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
4203                 MonoMethod *nm;
4204                 MonoMethodPInvoke* piinfo = (MonoMethodPInvoke *) method;
4205
4206                 if (!piinfo->addr) {
4207                         if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
4208                                 piinfo->addr = mono_lookup_internal_call (method);
4209                         else if (method->iflags & METHOD_IMPL_ATTRIBUTE_NATIVE)
4210 #ifdef HOST_WIN32
4211                                 g_warning ("Method '%s' in assembly '%s' contains native code that cannot be executed by Mono in modules loaded from byte arrays. The assembly was probably created using C++/CLI.\n", mono_method_full_name (method, TRUE), method->klass->image->name);
4212 #else
4213                                 g_warning ("Method '%s' in assembly '%s' contains native code that cannot be executed by Mono on this platform. The assembly was probably created using C++/CLI.\n", mono_method_full_name (method, TRUE), method->klass->image->name);
4214 #endif
4215                         else
4216                                 mono_lookup_pinvoke_call (method, NULL, NULL);
4217                 }
4218                 nm = mono_marshal_get_native_wrapper (method, TRUE, mono_aot_only);
4219                 gpointer compiled_method = mono_compile_method_checked (nm, error);
4220                 return_val_if_nok (error, NULL);
4221                 code = mono_get_addr_from_ftnptr (compiled_method);
4222                 jinfo = mono_jit_info_table_find (target_domain, (char *)code);
4223                 if (!jinfo)
4224                         jinfo = mono_jit_info_table_find (mono_domain_get (), (char *)code);
4225                 if (jinfo)
4226                         mono_profiler_method_end_jit (method, jinfo, MONO_PROFILE_OK);
4227                 return code;
4228         } else if ((method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
4229                 const char *name = method->name;
4230                 char *full_name, *msg;
4231                 MonoMethod *nm;
4232
4233                 if (method->klass->parent == mono_defaults.multicastdelegate_class) {
4234                         if (*name == '.' && (strcmp (name, ".ctor") == 0)) {
4235                                 MonoJitICallInfo *mi = mono_find_jit_icall_by_name ("mono_delegate_ctor");
4236                                 g_assert (mi);
4237                                 /*
4238                                  * We need to make sure this wrapper
4239                                  * is compiled because it might end up
4240                                  * in an (M)RGCTX if generic sharing
4241                                  * is enabled, and would be called
4242                                  * indirectly.  If it were a
4243                                  * trampoline we'd try to patch that
4244                                  * indirect call, which is not
4245                                  * possible.
4246                                  */
4247                                 return mono_get_addr_from_ftnptr ((gpointer)mono_icall_get_wrapper_full (mi, TRUE));
4248                         } else if (*name == 'I' && (strcmp (name, "Invoke") == 0)) {
4249                                 if (mono_llvm_only) {
4250                                         nm = mono_marshal_get_delegate_invoke (method, NULL);
4251                                         gpointer compiled_ptr = mono_compile_method_checked (nm, error);
4252                                         mono_error_assert_ok (error);
4253                                         return mono_get_addr_from_ftnptr (compiled_ptr);
4254                                 }
4255                                 return mono_create_delegate_trampoline (target_domain, method->klass);
4256                         } else if (*name == 'B' && (strcmp (name, "BeginInvoke") == 0)) {
4257                                 nm = mono_marshal_get_delegate_begin_invoke (method);
4258                                 gpointer compiled_ptr = mono_compile_method_checked (nm, error);
4259                                 mono_error_assert_ok (error);
4260                                 return mono_get_addr_from_ftnptr (compiled_ptr);
4261                         } else if (*name == 'E' && (strcmp (name, "EndInvoke") == 0)) {
4262                                 nm = mono_marshal_get_delegate_end_invoke (method);
4263                                 gpointer compiled_ptr = mono_compile_method_checked (nm, error);
4264                                 mono_error_assert_ok (error);
4265                                 return mono_get_addr_from_ftnptr (compiled_ptr);
4266                         }
4267                 }
4268
4269                 full_name = mono_method_full_name (method, TRUE);
4270                 msg = g_strdup_printf ("Unrecognizable runtime implemented method '%s'", full_name);
4271                 ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", msg);
4272                 mono_error_set_exception_instance (error, ex);
4273                 g_free (full_name);
4274                 g_free (msg);
4275                 return NULL;
4276         }
4277
4278         if (method->wrapper_type == MONO_WRAPPER_UNKNOWN) {
4279                 WrapperInfo *info = mono_marshal_get_wrapper_info (method);
4280
4281                 if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN || info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_OUT) {
4282                         static MonoTrampInfo *in_tinfo, *out_tinfo;
4283                         MonoTrampInfo *tinfo;
4284                         MonoJitInfo *jinfo;
4285                         gboolean is_in = info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN;
4286
4287                         if (is_in && in_tinfo)
4288                                 return in_tinfo->code;
4289                         else if (!is_in && out_tinfo)
4290                                 return out_tinfo->code;
4291
4292                         /*
4293                          * This is a special wrapper whose body is implemented in assembly, like a trampoline. We use a wrapper so EH
4294                          * works.
4295                          * FIXME: The caller signature doesn't match the callee, which might cause problems on some platforms
4296                          */
4297                         if (mono_aot_only)
4298                                 mono_aot_get_trampoline_full (is_in ? "gsharedvt_trampoline" : "gsharedvt_out_trampoline", &tinfo);
4299                         else
4300                                 mono_arch_get_gsharedvt_trampoline (&tinfo, FALSE);
4301                         jinfo = create_jit_info_for_trampoline (method, tinfo);
4302                         mono_jit_info_table_add (mono_get_root_domain (), jinfo);
4303                         if (is_in)
4304                                 in_tinfo = tinfo;
4305                         else
4306                                 out_tinfo = tinfo;
4307                         return tinfo->code;
4308                 }
4309         }
4310
4311         if (mono_aot_only) {
4312                 char *fullname = mono_method_full_name (method, TRUE);
4313                 char *msg = g_strdup_printf ("Attempting to JIT compile method '%s' while running with --aot-only. See http://docs.xamarin.com/ios/about/limitations for more information.\n", fullname);
4314
4315                 ex = mono_get_exception_execution_engine (msg);
4316                 mono_error_set_exception_instance (error, ex);
4317                 g_free (fullname);
4318                 g_free (msg);
4319                 
4320                 return NULL;
4321         }
4322
4323         jit_timer = mono_time_track_start ();
4324         cfg = mini_method_compile (method, opt, target_domain, JIT_FLAG_RUN_CCTORS, 0, -1);
4325         mono_time_track_end (&mono_jit_stats.jit_time, jit_timer);
4326
4327         prof_method = cfg->method;
4328
4329         switch (cfg->exception_type) {
4330         case MONO_EXCEPTION_NONE:
4331                 break;
4332         case MONO_EXCEPTION_TYPE_LOAD:
4333         case MONO_EXCEPTION_MISSING_FIELD:
4334         case MONO_EXCEPTION_MISSING_METHOD:
4335         case MONO_EXCEPTION_FILE_NOT_FOUND:
4336         case MONO_EXCEPTION_BAD_IMAGE:
4337         case MONO_EXCEPTION_INVALID_PROGRAM: {
4338                 /* Throw a type load exception if needed */
4339                 if (cfg->exception_ptr) {
4340                         ex = mono_class_get_exception_for_failure ((MonoClass *)cfg->exception_ptr);
4341                 } else {
4342                         if (cfg->exception_type == MONO_EXCEPTION_MISSING_FIELD)
4343                                 ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingFieldException", cfg->exception_message);
4344                         else if (cfg->exception_type == MONO_EXCEPTION_MISSING_METHOD)
4345                                 ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingMethodException", cfg->exception_message);
4346                         else if (cfg->exception_type == MONO_EXCEPTION_TYPE_LOAD)
4347                                 ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "TypeLoadException", cfg->exception_message);
4348                         else if (cfg->exception_type == MONO_EXCEPTION_FILE_NOT_FOUND)
4349                                 ex = mono_exception_from_name_msg (mono_defaults.corlib, "System.IO", "FileNotFoundException", cfg->exception_message);
4350                         else if (cfg->exception_type == MONO_EXCEPTION_BAD_IMAGE)
4351                                 ex = mono_get_exception_bad_image_format (cfg->exception_message);
4352                         else if (cfg->exception_type == MONO_EXCEPTION_INVALID_PROGRAM)
4353                                 ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", cfg->exception_message);
4354                         else
4355                                 g_assert_not_reached ();
4356                 }
4357                 break;
4358         }
4359         case MONO_EXCEPTION_MONO_ERROR:
4360                 // FIXME: MonoError has no copy ctor
4361                 g_assert (!mono_error_ok (&cfg->error));
4362                 ex = mono_error_convert_to_exception (&cfg->error);
4363                 break;
4364         default:
4365                 g_assert_not_reached ();
4366         }
4367
4368         if (ex) {
4369                 if (cfg->prof_options & MONO_PROFILE_JIT_COMPILATION)
4370                         mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_FAILED);
4371
4372                 mono_destroy_compile (cfg);
4373                 mono_error_set_exception_instance (error, ex);
4374
4375                 return NULL;
4376         }
4377
4378         if (mono_method_is_generic_sharable (method, FALSE))
4379                 shared = mini_get_shared_method (method);
4380         else
4381                 shared = NULL;
4382
4383         mono_domain_lock (target_domain);
4384
4385         /* Check if some other thread already did the job. In this case, we can
4386        discard the code this thread generated. */
4387
4388         info = mini_lookup_method (target_domain, method, shared);
4389         if (info) {
4390                 /* We can't use a domain specific method in another domain */
4391                 if ((target_domain == mono_domain_get ()) || info->domain_neutral) {
4392                         code = info->code_start;
4393 //                      printf("Discarding code for method %s\n", method->name);
4394                 }
4395         }
4396         if (code == NULL) {
4397                 /* The lookup + insert is atomic since this is done inside the domain lock */
4398                 mono_domain_jit_code_hash_lock (target_domain);
4399                 mono_internal_hash_table_insert (&target_domain->jit_code_hash, cfg->jit_info->d.method, cfg->jit_info);
4400                 mono_domain_jit_code_hash_unlock (target_domain);
4401
4402                 code = cfg->native_code;
4403
4404                 if (cfg->gshared && mono_method_is_generic_sharable (method, FALSE))
4405                         mono_stats.generics_shared_methods++;
4406                 if (cfg->gsharedvt)
4407                         mono_stats.gsharedvt_methods++;
4408         }
4409
4410         jinfo = cfg->jit_info;
4411
4412         prof_options = cfg->prof_options;
4413
4414         /*
4415          * Update global stats while holding a lock, instead of doing many
4416          * InterlockedIncrement operations during JITting.
4417          */
4418         mono_update_jit_stats (cfg);
4419
4420         mono_destroy_compile (cfg);
4421
4422 #ifndef DISABLE_JIT
4423         if (domain_jit_info (target_domain)->jump_target_hash) {
4424                 MonoJumpInfo patch_info;
4425                 MonoJumpList *jlist;
4426                 GSList *tmp;
4427                 jlist = (MonoJumpList *)g_hash_table_lookup (domain_jit_info (target_domain)->jump_target_hash, method);
4428                 if (jlist) {
4429                         patch_info.next = NULL;
4430                         patch_info.ip.i = 0;
4431                         patch_info.type = MONO_PATCH_INFO_METHOD_JUMP;
4432                         patch_info.data.method = method;
4433                         g_hash_table_remove (domain_jit_info (target_domain)->jump_target_hash, method);
4434
4435 #if defined(__native_client_codegen__) && defined(__native_client__)
4436                         /* These patches are applied after a method has been installed, no target munging is needed. */
4437                         nacl_allow_target_modification (FALSE);
4438 #endif
4439 #ifdef MONO_ARCH_HAVE_PATCH_CODE_NEW
4440                         for (tmp = jlist->list; tmp; tmp = tmp->next) {
4441                                 gpointer target = mono_resolve_patch_target (NULL, target_domain, (guint8 *)tmp->data, &patch_info, TRUE, error);
4442                                 if (!mono_error_ok (error))
4443                                         break;
4444                                 mono_arch_patch_code_new (NULL, target_domain, (guint8 *)tmp->data, &patch_info, target);
4445                         }
4446 #else
4447                         for (tmp = jlist->list; tmp; tmp = tmp->next)
4448                                 mono_arch_patch_code (NULL, NULL, target_domain, tmp->data, &patch_info, TRUE);
4449 #endif
4450 #if defined(__native_client_codegen__) && defined(__native_client__)
4451                         nacl_allow_target_modification (TRUE);
4452 #endif
4453                 }
4454         }
4455
4456         /* Update llvm callees */
4457         if (domain_jit_info (target_domain)->llvm_jit_callees) {
4458                 GSList *callees = g_hash_table_lookup (domain_jit_info (target_domain)->llvm_jit_callees, method);
4459                 GSList *l;
4460
4461                 for (l = callees; l; l = l->next) {
4462                         gpointer *addr = (gpointer*)l->data;
4463
4464                         *addr = code;
4465                 }
4466         }
4467
4468         mono_emit_jit_map (jinfo);
4469 #endif
4470         mono_domain_unlock (target_domain);
4471
4472         if (!mono_error_ok (error))
4473                 return NULL;
4474
4475         vtable = mono_class_vtable (target_domain, method->klass);
4476         if (!vtable) {
4477                 ex = mono_class_get_exception_for_failure (method->klass);
4478                 g_assert (ex);
4479                 mono_error_set_exception_instance (error, ex);
4480                 return NULL;
4481         }
4482
4483         if (prof_options & MONO_PROFILE_JIT_COMPILATION) {
4484                 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
4485                         if (mono_marshal_method_from_wrapper (method)) {
4486                                 /* Native func wrappers have no method */
4487                                 /* The profiler doesn't know about wrappers, so pass the original icall method */
4488                                 mono_profiler_method_end_jit (mono_marshal_method_from_wrapper (method), jinfo, MONO_PROFILE_OK);
4489                         }
4490                 }
4491                 mono_profiler_method_end_jit (method, jinfo, MONO_PROFILE_OK);
4492                 if (prof_method != method) {
4493                         mono_profiler_method_end_jit (prof_method, jinfo, MONO_PROFILE_OK);
4494                 }
4495         }
4496
4497         if (!mono_runtime_class_init_full (vtable, error))
4498                 return NULL;
4499         return code;
4500 }
4501
4502 /*
4503  * mini_get_underlying_type:
4504  *
4505  *   Return the type the JIT will use during compilation.
4506  * Handles: byref, enums, native types, generic sharing.
4507  * For gsharedvt types, it will return the original VAR/MVAR.
4508  */
4509 MonoType*
4510 mini_get_underlying_type (MonoType *type)
4511 {
4512         return mini_type_get_underlying_type (type);
4513 }
4514
4515 void
4516 mini_jit_init (void)
4517 {
4518         mono_os_mutex_init_recursive (&jit_mutex);
4519 #ifndef DISABLE_JIT
4520         current_backend = g_new0 (MonoBackend, 1);
4521         init_backend (current_backend);
4522 #endif
4523 }
4524
4525 void
4526 mini_jit_cleanup (void)
4527 {
4528 #ifndef DISABLE_JIT
4529         g_free (emul_opcode_map);
4530         g_free (emul_opcode_opcodes);
4531 #endif
4532 }
4533
4534 #ifndef ENABLE_LLVM
4535 void
4536 mono_llvm_emit_aot_file_info (MonoAotFileInfo *info, gboolean has_jitted_code)
4537 {
4538         g_assert_not_reached ();
4539 }
4540
4541 void mono_llvm_emit_aot_data (const char *symbol, guint8 *data, int data_len)
4542 {
4543         g_assert_not_reached ();
4544 }
4545
4546 #endif
4547
4548 #if !defined(ENABLE_LLVM_RUNTIME) && !defined(ENABLE_LLVM)
4549
4550 void
4551 mono_llvm_cpp_throw_exception (void)
4552 {
4553         g_assert_not_reached ();
4554 }
4555
4556 #endif
4557
4558 #ifdef DISABLE_JIT
4559
4560 MonoCompile*
4561 mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFlags flags, int parts, int aot_method_index)
4562 {
4563         g_assert_not_reached ();
4564         return NULL;
4565 }
4566
4567 void
4568 mono_destroy_compile (MonoCompile *cfg)
4569 {
4570         g_assert_not_reached ();
4571 }
4572
4573 void
4574 mono_add_patch_info (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target)
4575 {
4576         g_assert_not_reached ();
4577 }
4578
4579 #endif /* DISABLE_JIT */