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