Merge pull request #2124 from mhutch/mono-api-info-forwarders
[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 static void
3053 mono_create_gc_safepoint (MonoCompile *cfg, MonoBasicBlock *bblock)
3054 {
3055         MonoInst *poll_addr, *ins;
3056         if (cfg->verbose_level > 1)
3057                 printf ("ADDING SAFE POINT TO BB %d\n", bblock->block_num);
3058
3059 #if defined(__native_client_codegen__)
3060         NEW_AOTCONST (cfg, poll_addr, MONO_PATCH_INFO_GC_SAFE_POINT_FLAG, (gpointer)&__nacl_thread_suspension_needed);
3061 #else
3062         g_assert (mono_threads_is_coop_enabled ());
3063         NEW_AOTCONST (cfg, poll_addr, MONO_PATCH_INFO_GC_SAFE_POINT_FLAG, (gpointer)&mono_polling_required);
3064 #endif
3065
3066         MONO_INST_NEW (cfg, ins, OP_GC_SAFE_POINT);
3067         ins->sreg1 = poll_addr->dreg;
3068
3069          if (bblock->flags & BB_EXCEPTION_HANDLER) {
3070                 MonoInst *eh_op = bblock->code;
3071
3072                 if (eh_op && eh_op->opcode != OP_START_HANDLER && eh_op->opcode != OP_GET_EX_OBJ) {
3073                         eh_op = NULL;
3074                 } else {
3075                         MonoInst *next_eh_op = eh_op ? eh_op->next : NULL;
3076                         // skip all EH relateds ops
3077                         while (next_eh_op && (next_eh_op->opcode == OP_START_HANDLER || next_eh_op->opcode == OP_GET_EX_OBJ)) {
3078                                 eh_op = next_eh_op;
3079                                 next_eh_op = eh_op->next;
3080                         }
3081                 }
3082
3083                 mono_bblock_insert_after_ins (bblock, eh_op, poll_addr);
3084                 mono_bblock_insert_after_ins (bblock, poll_addr, ins);
3085         } else if (bblock == cfg->bb_entry) {
3086                 mono_bblock_insert_after_ins (bblock, bblock->last_ins, poll_addr);
3087                 mono_bblock_insert_after_ins (bblock, poll_addr, ins);
3088
3089         } else {
3090                 mono_bblock_insert_before_ins (bblock, NULL, poll_addr);
3091                 mono_bblock_insert_after_ins (bblock, poll_addr, ins);
3092         }
3093 }
3094
3095 /*
3096 This code inserts safepoints into managed code at important code paths.
3097 Those are:
3098
3099 -the first basic block
3100 -landing BB for exception handlers
3101 -loop body starts.
3102
3103 */
3104 static void
3105 mono_insert_safepoints (MonoCompile *cfg)
3106 {
3107         MonoBasicBlock *bb;
3108
3109 #if !defined(__native_client_codegen__)
3110         if (!mono_threads_is_coop_enabled ())
3111                 return;
3112 #endif
3113
3114         if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
3115                 WrapperInfo *info = mono_marshal_get_wrapper_info (cfg->method);
3116 #if defined(__native_client__) || defined(__native_client_codegen__)
3117                 gpointer poll_func = &mono_nacl_gc;
3118 #else
3119                 g_assert (mono_threads_is_coop_enabled ());
3120                 gpointer poll_func = &mono_threads_state_poll;
3121 #endif
3122
3123                 if (info && info->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER && info->d.icall.func == poll_func) {
3124                         if (cfg->verbose_level > 1)
3125                                 printf ("SKIPPING SAFEPOINTS for the polling function icall\n");
3126                         return;
3127                 }
3128         }
3129
3130         if (cfg->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
3131                 if (cfg->verbose_level > 1)
3132                         printf ("SKIPPING SAFEPOINTS for native-to-managed wrappers.\n");
3133                 return;
3134         }
3135
3136         if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
3137                 WrapperInfo *info = mono_marshal_get_wrapper_info (cfg->method);
3138
3139                 if (info && info->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER &&
3140                         (info->d.icall.func == mono_thread_interruption_checkpoint ||
3141                         info->d.icall.func == mono_threads_finish_blocking ||
3142                         info->d.icall.func == mono_threads_reset_blocking_start)) {
3143                         /* These wrappers are called from the wrapper for the polling function, leading to potential stack overflow */
3144                         if (cfg->verbose_level > 1)
3145                                 printf ("SKIPPING SAFEPOINTS for wrapper %s\n", cfg->method->name);
3146                         return;
3147                 }
3148         }
3149
3150         if (cfg->verbose_level > 1)
3151                 printf ("INSERTING SAFEPOINTS\n");
3152         if (cfg->verbose_level > 2)
3153                 mono_print_code (cfg, "BEFORE SAFEPOINTS");
3154
3155         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
3156                 if (bb->loop_body_start || bb == cfg->bb_entry || bb->flags & BB_EXCEPTION_HANDLER)
3157                         mono_create_gc_safepoint (cfg, bb);
3158         }
3159
3160         if (cfg->verbose_level > 2)
3161                 mono_print_code (cfg, "AFTER SAFEPOINTS");
3162
3163 }
3164
3165 static void
3166 init_backend (MonoBackend *backend)
3167 {
3168 #ifdef MONO_ARCH_NEED_GOT_VAR
3169         backend->need_got_var = 1;
3170 #endif
3171 #ifdef MONO_ARCH_HAVE_CARD_TABLE_WBARRIER
3172         backend->have_card_table_wb = 1;
3173 #endif
3174 #ifdef MONO_ARCH_HAVE_OP_GENERIC_CLASS_INIT
3175         backend->have_op_generic_class_init = 1;
3176 #endif
3177 #ifdef MONO_ARCH_EMULATE_MUL_DIV
3178         backend->emulate_mul_div = 1;
3179 #endif
3180 #ifdef MONO_ARCH_EMULATE_DIV
3181         backend->emulate_div = 1;
3182 #endif
3183 #if !defined(MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS)
3184         backend->emulate_long_shift_opts = 1;
3185 #endif
3186 #ifdef MONO_ARCH_HAVE_OBJC_GET_SELECTOR
3187         backend->have_objc_get_selector = 1;
3188 #endif
3189 #ifdef MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK
3190         backend->have_generalized_imt_thunk = 1;
3191 #endif
3192 #ifdef MONO_ARCH_GSHARED_SUPPORTED
3193         backend->gshared_supported = 1;
3194 #endif
3195         if (MONO_ARCH_HAVE_TLS_GET)
3196                 backend->have_tls_get = 1;
3197 #ifdef MONO_ARCH_HAVE_TLS_GET_REG
3198                 backend->have_tls_get_reg = 1;
3199 #endif
3200         if (MONO_ARCH_USE_FPSTACK)
3201                 backend->use_fpstack = 1;
3202 #ifdef MONO_ARCH_HAVE_LIVERANGE_OPS
3203         backend->have_liverange_ops = 1;
3204 #endif
3205 #ifdef MONO_ARCH_HAVE_OP_TAIL_CALL
3206         backend->have_op_tail_call = 1;
3207 #endif
3208 #ifndef MONO_ARCH_MONITOR_ENTER_ADJUSTMENT
3209         backend->monitor_enter_adjustment = 1;
3210 #else
3211         backend->monitor_enter_adjustment = MONO_ARCH_MONITOR_ENTER_ADJUSTMENT;
3212 #endif
3213 #if defined(__mono_ilp32__)
3214         backend->ilp32 = 1;
3215 #endif
3216 #ifdef MONO_ARCH_HAVE_DUMMY_INIT
3217         backend->have_dummy_init = 1;
3218 #endif
3219 #ifdef MONO_ARCH_NEED_DIV_CHECK
3220         backend->need_div_check = 1;
3221 #endif
3222 #ifdef NO_UNALIGNED_ACCESS
3223         backend->no_unaligned_access = 1;
3224 #endif
3225 #ifdef MONO_ARCH_DYN_CALL_PARAM_AREA
3226         backend->dyn_call_param_area = MONO_ARCH_DYN_CALL_PARAM_AREA;
3227 #endif
3228 }
3229
3230 /*
3231  * mini_method_compile:
3232  * @method: the method to compile
3233  * @opts: the optimization flags to use
3234  * @domain: the domain where the method will be compiled in
3235  * @flags: compilation flags
3236  * @parts: debug flag
3237  *
3238  * Returns: a MonoCompile* pointer. Caller must check the exception_type
3239  * field in the returned struct to see if compilation succeded.
3240  */
3241 MonoCompile*
3242 mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFlags flags, int parts, int aot_method_index)
3243 {
3244         MonoMethodHeader *header;
3245         MonoMethodSignature *sig;
3246         MonoError err;
3247         MonoCompile *cfg;
3248         int dfn, i, code_size_ratio;
3249         gboolean try_generic_shared, try_llvm = FALSE;
3250         MonoMethod *method_to_compile, *method_to_register;
3251         gboolean method_is_gshared = FALSE;
3252         gboolean run_cctors = (flags & JIT_FLAG_RUN_CCTORS) ? 1 : 0;
3253         gboolean compile_aot = (flags & JIT_FLAG_AOT) ? 1 : 0;
3254         gboolean full_aot = (flags & JIT_FLAG_FULL_AOT) ? 1 : 0;
3255         gboolean disable_direct_icalls = (flags & JIT_FLAG_NO_DIRECT_ICALLS) ? 1 : 0;
3256         gboolean gsharedvt_method = FALSE;
3257 #ifdef ENABLE_LLVM
3258         gboolean llvm = (flags & JIT_FLAG_LLVM) ? 1 : 0;
3259 #endif
3260         static gboolean verbose_method_inited;
3261         static const char *verbose_method_name;
3262
3263         InterlockedIncrement (&mono_jit_stats.methods_compiled);
3264         if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)
3265                 mono_profiler_method_jit (method);
3266         if (MONO_METHOD_COMPILE_BEGIN_ENABLED ())
3267                 MONO_PROBE_METHOD_COMPILE_BEGIN (method);
3268
3269         gsharedvt_method = is_gsharedvt_method (method);
3270
3271         /*
3272          * In AOT mode, method can be the following:
3273          * - a gsharedvt method.
3274          * - a method inflated with type parameters. This is for ref/partial sharing.
3275          * - a method inflated with concrete types.
3276          */
3277         if (compile_aot) {
3278                 if (is_open_method (method)) {
3279                         try_generic_shared = TRUE;
3280                         method_is_gshared = TRUE;
3281                 } else {
3282                         try_generic_shared = FALSE;
3283                 }
3284                 g_assert (opts & MONO_OPT_GSHARED);
3285         } else {
3286                 try_generic_shared = mono_class_generic_sharing_enabled (method->klass) &&
3287                         (opts & MONO_OPT_GSHARED) && mono_method_is_generic_sharable (method, FALSE);
3288                 if (mini_is_gsharedvt_sharable_method (method)) {
3289                         if (!mono_debug_count ())
3290                                 try_generic_shared = FALSE;
3291                 }
3292         }
3293
3294         /*
3295         if (try_generic_shared && !mono_debug_count ())
3296                 try_generic_shared = FALSE;
3297         */
3298
3299         if (opts & MONO_OPT_GSHARED) {
3300                 if (try_generic_shared)
3301                         mono_stats.generics_sharable_methods++;
3302                 else if (mono_method_is_generic_impl (method))
3303                         mono_stats.generics_unsharable_methods++;
3304         }
3305
3306 #ifdef ENABLE_LLVM
3307         try_llvm = mono_use_llvm || llvm;
3308 #endif
3309
3310  restart_compile:
3311         if (method_is_gshared) {
3312                 method_to_compile = method;
3313         } else {
3314                 if (try_generic_shared) {
3315                         method_to_compile = mini_get_shared_method (method);
3316                         g_assert (method_to_compile);
3317                 } else {
3318                         method_to_compile = method;
3319                 }
3320         }
3321
3322         cfg = g_new0 (MonoCompile, 1);
3323         cfg->method = method_to_compile;
3324         cfg->header = mono_method_get_header (cfg->method);
3325         cfg->mempool = mono_mempool_new ();
3326         cfg->opt = opts;
3327         cfg->prof_options = mono_profiler_get_events ();
3328         cfg->run_cctors = run_cctors;
3329         cfg->domain = domain;
3330         cfg->verbose_level = mini_verbose;
3331         cfg->compile_aot = compile_aot;
3332         cfg->full_aot = full_aot;
3333         cfg->skip_visibility = method->skip_visibility;
3334         cfg->orig_method = method;
3335         cfg->gen_seq_points = debug_options.gen_seq_points_compact_data || debug_options.gen_sdb_seq_points;
3336         cfg->gen_sdb_seq_points = debug_options.gen_sdb_seq_points;
3337         cfg->llvm_only = (flags & JIT_FLAG_LLVM_ONLY) != 0;
3338         cfg->backend = current_backend;
3339
3340 #ifdef PLATFORM_ANDROID
3341         if (cfg->method->wrapper_type != MONO_WRAPPER_NONE) {
3342                 /* FIXME: Why is this needed */
3343                 cfg->gen_seq_points = FALSE;
3344                 cfg->gen_sdb_seq_points = FALSE;
3345         }
3346 #endif
3347         /* coop / nacl requires loop detection to happen */
3348 #if defined(__native_client_codegen__)
3349         cfg->opt |= MONO_OPT_LOOP;
3350 #else
3351         if (mono_threads_is_coop_enabled ())
3352                 cfg->opt |= MONO_OPT_LOOP;
3353 #endif
3354         cfg->explicit_null_checks = debug_options.explicit_null_checks || (flags & JIT_FLAG_EXPLICIT_NULL_CHECKS);
3355         cfg->soft_breakpoints = debug_options.soft_breakpoints;
3356         cfg->check_pinvoke_callconv = debug_options.check_pinvoke_callconv;
3357         cfg->disable_direct_icalls = disable_direct_icalls;
3358         if (try_generic_shared)
3359                 cfg->gshared = TRUE;
3360         cfg->compile_llvm = try_llvm;
3361         cfg->token_info_hash = g_hash_table_new (NULL, NULL);
3362         if (cfg->compile_aot)
3363                 cfg->method_index = aot_method_index;
3364
3365         /*
3366         if (!mono_debug_count ())
3367                 cfg->opt &= ~MONO_OPT_FLOAT32;
3368         */
3369         if (cfg->llvm_only)
3370                 cfg->opt &= ~MONO_OPT_SIMD;
3371         cfg->r4fp = (cfg->opt & MONO_OPT_FLOAT32) ? 1 : 0;
3372         cfg->r4_stack_type = cfg->r4fp ? STACK_R4 : STACK_R8;
3373
3374         if (cfg->gen_seq_points)
3375                 cfg->seq_points = g_ptr_array_new ();
3376         mono_error_init (&cfg->error);
3377
3378         if (cfg->compile_aot && !try_generic_shared && (method->is_generic || method->klass->generic_container || method_is_gshared)) {
3379                 cfg->exception_type = MONO_EXCEPTION_GENERIC_SHARING_FAILED;
3380                 return cfg;
3381         }
3382
3383         if (cfg->gshared && (gsharedvt_method || mini_is_gsharedvt_sharable_method (method))) {
3384                 MonoMethodInflated *inflated;
3385                 MonoGenericContext *context;
3386
3387                 if (gsharedvt_method) {
3388                         g_assert (method->is_inflated);
3389                         inflated = (MonoMethodInflated*)method;
3390                         context = &inflated->context;
3391
3392                         /* We are compiling a gsharedvt method directly */
3393                         g_assert (compile_aot);
3394                 } else {
3395                         g_assert (method_to_compile->is_inflated);
3396                         inflated = (MonoMethodInflated*)method_to_compile;
3397                         context = &inflated->context;
3398                 }
3399
3400                 mini_init_gsctx (NULL, cfg->mempool, context, &cfg->gsctx);
3401                 cfg->gsctx_context = context;
3402
3403                 cfg->gsharedvt = TRUE;
3404                 // FIXME:
3405                 cfg->disable_llvm = TRUE;
3406                 cfg->exception_message = g_strdup ("gsharedvt");
3407         }
3408
3409         if (cfg->gshared) {
3410                 method_to_register = method_to_compile;
3411         } else {
3412                 g_assert (method == method_to_compile);
3413                 method_to_register = method;
3414         }
3415         cfg->method_to_register = method_to_register;
3416
3417         mono_error_init (&err);
3418         sig = mono_method_signature_checked (cfg->method, &err);        
3419         if (!sig) {
3420                 cfg->exception_type = MONO_EXCEPTION_TYPE_LOAD;
3421                 cfg->exception_message = g_strdup (mono_error_get_message (&err));
3422                 mono_error_cleanup (&err);
3423                 if (MONO_METHOD_COMPILE_END_ENABLED ())
3424                         MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
3425                 return cfg;
3426         }
3427
3428         header = cfg->header;
3429         if (!header) {
3430                 MonoLoaderError *error;
3431
3432                 if ((error = mono_loader_get_last_error ())) {
3433                         cfg->exception_type = error->exception_type;
3434                 } else {
3435                         cfg->exception_type = MONO_EXCEPTION_INVALID_PROGRAM;
3436                         cfg->exception_message = g_strdup_printf ("Missing or incorrect header for method %s", cfg->method->name);
3437                 }
3438                 if (MONO_METHOD_COMPILE_END_ENABLED ())
3439                         MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
3440                 return cfg;
3441         }
3442
3443 #ifdef ENABLE_LLVM
3444         {
3445                 static gboolean inited;
3446
3447                 if (!inited)
3448                         inited = TRUE;
3449
3450                 /* 
3451                  * Check for methods which cannot be compiled by LLVM early, to avoid
3452                  * the extra compilation pass.
3453                  */
3454                 if (COMPILE_LLVM (cfg)) {
3455                         mono_llvm_check_method_supported (cfg);
3456                         if (cfg->disable_llvm) {
3457                                 if (cfg->verbose_level >= cfg->llvm_only ? 0 : 1) {
3458                                         //nm = mono_method_full_name (cfg->method, TRUE);
3459                                         printf ("LLVM failed for '%s': %s\n", method->name, cfg->exception_message);
3460                                         //g_free (nm);
3461                                 }
3462                                 if (cfg->llvm_only) {
3463                                         cfg->disable_aot = TRUE;
3464                                         return cfg;
3465                                 }
3466                                 mono_destroy_compile (cfg);
3467                                 try_llvm = FALSE;
3468                                 goto restart_compile;
3469                         }
3470                 }
3471         }
3472 #endif
3473
3474         /* The debugger has no liveness information, so avoid sharing registers/stack slots */
3475         if (debug_options.mdb_optimizations) {
3476                 cfg->disable_reuse_registers = TRUE;
3477                 cfg->disable_reuse_stack_slots = TRUE;
3478                 /* 
3479                  * This decreases the change the debugger will read registers/stack slots which are
3480                  * not yet initialized.
3481                  */
3482                 cfg->disable_initlocals_opt = TRUE;
3483
3484                 cfg->extend_live_ranges = TRUE;
3485
3486                 /* Temporarily disable this when running in the debugger until we have support
3487                  * for this in the debugger. */
3488                 /* This is no longer needed with sdb */
3489                 //cfg->disable_omit_fp = TRUE;
3490
3491                 /* The debugger needs all locals to be on the stack or in a global register */
3492                 cfg->disable_vreg_to_lvreg = TRUE;
3493
3494                 /* Don't remove unused variables when running inside the debugger since the user
3495                  * may still want to view them. */
3496                 cfg->disable_deadce_vars = TRUE;
3497
3498                 // cfg->opt |= MONO_OPT_SHARED;
3499                 cfg->opt &= ~MONO_OPT_DEADCE;
3500                 cfg->opt &= ~MONO_OPT_INLINE;
3501                 cfg->opt &= ~MONO_OPT_COPYPROP;
3502                 cfg->opt &= ~MONO_OPT_CONSPROP;
3503                 /* This is no longer needed with sdb */
3504                 //cfg->opt &= ~MONO_OPT_GSHARED;
3505
3506                 /* This is needed for the soft debugger, which doesn't like code after the epilog */
3507                 cfg->disable_out_of_line_bblocks = TRUE;
3508         }
3509
3510         if (mono_using_xdebug) {
3511                 /* 
3512                  * Make each variable use its own register/stack slot and extend 
3513                  * their liveness to cover the whole method, making them displayable
3514                  * in gdb even after they are dead.
3515                  */
3516                 cfg->disable_reuse_registers = TRUE;
3517                 cfg->disable_reuse_stack_slots = TRUE;
3518                 cfg->extend_live_ranges = TRUE;
3519                 cfg->compute_precise_live_ranges = TRUE;
3520         }
3521
3522         mini_gc_init_cfg (cfg);
3523
3524         if (COMPILE_LLVM (cfg)) {
3525                 cfg->opt |= MONO_OPT_ABCREM;
3526         }
3527
3528         if (!verbose_method_inited) {
3529                 verbose_method_name = g_getenv ("MONO_VERBOSE_METHOD");
3530                 verbose_method_inited = TRUE;
3531         }
3532         if (verbose_method_name) {
3533                 const char *name = verbose_method_name;
3534
3535                 if ((strchr (name, '.') > name) || strchr (name, ':')) {
3536                         MonoMethodDesc *desc;
3537                         
3538                         desc = mono_method_desc_new (name, TRUE);
3539                         if (mono_method_desc_full_match (desc, cfg->method)) {
3540                                 cfg->verbose_level = 4;
3541                         }
3542                         mono_method_desc_free (desc);
3543                 } else {
3544                         if (strcmp (cfg->method->name, name) == 0)
3545                                 cfg->verbose_level = 4;
3546                 }
3547         }
3548
3549         cfg->intvars = mono_mempool_alloc0 (cfg->mempool, sizeof (guint16) * STACK_MAX * header->max_stack);
3550
3551         if (cfg->verbose_level > 0) {
3552                 char *method_name;
3553
3554                 method_name = mono_method_full_name (method, TRUE);
3555                 g_print ("converting %s%s%smethod %s\n", COMPILE_LLVM (cfg) ? "llvm " : "", cfg->gsharedvt ? "gsharedvt " : "", (cfg->gshared && !cfg->gsharedvt) ? "gshared " : "", method_name);
3556                 /*
3557                 if (COMPILE_LLVM (cfg))
3558                         g_print ("converting llvm method %s\n", method_name = mono_method_full_name (method, TRUE));
3559                 else if (cfg->gsharedvt)
3560                         g_print ("converting gsharedvt method %s\n", method_name = mono_method_full_name (method_to_compile, TRUE));
3561                 else if (cfg->gshared)
3562                         g_print ("converting shared method %s\n", method_name = mono_method_full_name (method_to_compile, TRUE));
3563                 else
3564                         g_print ("converting method %s\n", method_name = mono_method_full_name (method, TRUE));
3565                 */
3566                 g_free (method_name);
3567         }
3568
3569         if (cfg->opt & MONO_OPT_ABCREM)
3570                 cfg->opt |= MONO_OPT_SSA;
3571
3572         cfg->rs = mono_regstate_new ();
3573         cfg->next_vreg = cfg->rs->next_vreg;
3574
3575         /* FIXME: Fix SSA to handle branches inside bblocks */
3576         if (cfg->opt & MONO_OPT_SSA)
3577                 cfg->enable_extended_bblocks = FALSE;
3578
3579         /*
3580          * FIXME: This confuses liveness analysis because variables which are assigned after
3581          * a branch inside a bblock become part of the kill set, even though the assignment
3582          * might not get executed. This causes the optimize_initlocals pass to delete some
3583          * assignments which are needed.
3584          * Also, the mono_if_conversion pass needs to be modified to recognize the code
3585          * created by this.
3586          */
3587         //cfg->enable_extended_bblocks = TRUE;
3588
3589         /*We must verify the method before doing any IR generation as mono_compile_create_vars can assert.*/
3590         if (mono_compile_is_broken (cfg, cfg->method, TRUE)) {
3591                 if (mini_get_debug_options ()->break_on_unverified)
3592                         G_BREAKPOINT ();
3593                 return cfg;
3594         }
3595
3596         /*
3597          * create MonoInst* which represents arguments and local variables
3598          */
3599         mono_compile_create_vars (cfg);
3600
3601         i = mono_method_to_ir (cfg, method_to_compile, NULL, NULL, NULL, NULL, 0, FALSE);
3602
3603         if (i < 0) {
3604                 if (try_generic_shared && cfg->exception_type == MONO_EXCEPTION_GENERIC_SHARING_FAILED) {
3605                         if (compile_aot) {
3606                                 if (MONO_METHOD_COMPILE_END_ENABLED ())
3607                                         MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
3608                                 return cfg;
3609                         }
3610                         mono_destroy_compile (cfg);
3611                         try_generic_shared = FALSE;
3612                         goto restart_compile;
3613                 }
3614                 g_assert (cfg->exception_type != MONO_EXCEPTION_GENERIC_SHARING_FAILED);
3615
3616                 if (MONO_METHOD_COMPILE_END_ENABLED ())
3617                         MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
3618                 /* cfg contains the details of the failure, so let the caller cleanup */
3619                 return cfg;
3620         }
3621
3622         cfg->stat_basic_blocks += cfg->num_bblocks;
3623
3624         if (COMPILE_LLVM (cfg)) {
3625                 MonoInst *ins;
3626
3627                 /* The IR has to be in SSA form for LLVM */
3628                 cfg->opt |= MONO_OPT_SSA;
3629
3630                 // FIXME:
3631                 if (cfg->ret) {
3632                         // Allow SSA on the result value
3633                         cfg->ret->flags &= ~MONO_INST_VOLATILE;
3634
3635                         // Add an explicit return instruction referencing the return value
3636                         MONO_INST_NEW (cfg, ins, OP_SETRET);
3637                         ins->sreg1 = cfg->ret->dreg;
3638
3639                         MONO_ADD_INS (cfg->bb_exit, ins);
3640                 }
3641
3642                 cfg->opt &= ~MONO_OPT_LINEARS;
3643
3644                 /* FIXME: */
3645                 cfg->opt &= ~MONO_OPT_BRANCH;
3646         }
3647
3648         /* todo: remove code when we have verified that the liveness for try/catch blocks
3649          * works perfectly 
3650          */
3651         /* 
3652          * Currently, this can't be commented out since exception blocks are not
3653          * processed during liveness analysis.
3654          * It is also needed, because otherwise the local optimization passes would
3655          * delete assignments in cases like this:
3656          * r1 <- 1
3657          * <something which throws>
3658          * r1 <- 2
3659          * This also allows SSA to be run on methods containing exception clauses, since
3660          * SSA will ignore variables marked VOLATILE.
3661          */
3662         mono_liveness_handle_exception_clauses (cfg);
3663
3664         mono_handle_out_of_line_bblock (cfg);
3665
3666         /*g_print ("numblocks = %d\n", cfg->num_bblocks);*/
3667
3668         if (!COMPILE_LLVM (cfg))
3669                 mono_decompose_long_opts (cfg);
3670
3671         /* Should be done before branch opts */
3672         if (cfg->opt & (MONO_OPT_CONSPROP | MONO_OPT_COPYPROP))
3673                 mono_local_cprop (cfg);
3674
3675         if (cfg->opt & MONO_OPT_BRANCH)
3676                 mono_optimize_branches (cfg);
3677
3678         /* This must be done _before_ global reg alloc and _after_ decompose */
3679         mono_handle_global_vregs (cfg);
3680         if (cfg->opt & MONO_OPT_DEADCE)
3681                 mono_local_deadce (cfg);
3682         if (cfg->opt & MONO_OPT_ALIAS_ANALYSIS)
3683                 mono_local_alias_analysis (cfg);
3684         /* Disable this for LLVM to make the IR easier to handle */
3685         if (!COMPILE_LLVM (cfg))
3686                 mono_if_conversion (cfg);
3687
3688         mono_threads_safepoint ();
3689
3690         /* Depth-first ordering on basic blocks */
3691         cfg->bblocks = mono_mempool_alloc (cfg->mempool, sizeof (MonoBasicBlock*) * (cfg->num_bblocks + 1));
3692
3693         cfg->max_block_num = cfg->num_bblocks;
3694
3695         dfn = 0;
3696         df_visit (cfg->bb_entry, &dfn, cfg->bblocks);
3697         if (cfg->num_bblocks != dfn + 1) {
3698                 MonoBasicBlock *bb;
3699
3700                 cfg->num_bblocks = dfn + 1;
3701
3702                 /* remove unreachable code, because the code in them may be 
3703                  * inconsistent  (access to dead variables for example) */
3704                 for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
3705                         bb->flags &= ~BB_VISITED;
3706                 compute_reachable (cfg->bb_entry);
3707                 for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
3708                         if (bb->flags & BB_EXCEPTION_HANDLER)
3709                                 compute_reachable (bb);
3710                 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
3711                         if (!(bb->flags & BB_VISITED)) {
3712                                 if (cfg->verbose_level > 1)
3713                                         g_print ("found unreachable code in BB%d\n", bb->block_num);
3714                                 bb->code = bb->last_ins = NULL;
3715                                 while (bb->out_count)
3716                                         mono_unlink_bblock (cfg, bb, bb->out_bb [0]);
3717                         }
3718                 }
3719                 for (bb = cfg->bb_entry; bb; bb = bb->next_bb)
3720                         bb->flags &= ~BB_VISITED;
3721         }
3722
3723         if (((cfg->num_varinfo > 2000) || (cfg->num_bblocks > 1000)) && !cfg->compile_aot) {
3724                 /* 
3725                  * we disable some optimizations if there are too many variables
3726                  * because JIT time may become too expensive. The actual number needs 
3727                  * to be tweaked and eventually the non-linear algorithms should be fixed.
3728                  */
3729                 cfg->opt &= ~ (MONO_OPT_LINEARS | MONO_OPT_COPYPROP | MONO_OPT_CONSPROP);
3730                 cfg->disable_ssa = TRUE;
3731         }
3732
3733         if (cfg->opt & MONO_OPT_LOOP) {
3734                 mono_compile_dominator_info (cfg, MONO_COMP_DOM | MONO_COMP_IDOM);
3735                 mono_compute_natural_loops (cfg);
3736         }
3737
3738         mono_insert_safepoints (cfg);
3739
3740         /* after method_to_ir */
3741         if (parts == 1) {
3742                 if (MONO_METHOD_COMPILE_END_ENABLED ())
3743                         MONO_PROBE_METHOD_COMPILE_END (method, TRUE);
3744                 return cfg;
3745         }
3746
3747         /*
3748           if (header->num_clauses)
3749           cfg->disable_ssa = TRUE;
3750         */
3751
3752 //#define DEBUGSSA "logic_run"
3753 //#define DEBUGSSA_CLASS "Tests"
3754 #ifdef DEBUGSSA
3755
3756         if (!cfg->disable_ssa) {
3757                 mono_local_cprop (cfg);
3758
3759 #ifndef DISABLE_SSA
3760                 mono_ssa_compute (cfg);
3761 #endif
3762         }
3763 #else 
3764         if (cfg->opt & MONO_OPT_SSA) {
3765                 if (!(cfg->comp_done & MONO_COMP_SSA) && !cfg->disable_ssa) {
3766 #ifndef DISABLE_SSA
3767                         mono_ssa_compute (cfg);
3768 #endif
3769
3770                         if (cfg->verbose_level >= 2) {
3771                                 print_dfn (cfg);
3772                         }
3773                 }
3774         }
3775 #endif
3776
3777         /* after SSA translation */
3778         if (parts == 2) {
3779                 if (MONO_METHOD_COMPILE_END_ENABLED ())
3780                         MONO_PROBE_METHOD_COMPILE_END (method, TRUE);
3781                 return cfg;
3782         }
3783
3784         if ((cfg->opt & MONO_OPT_CONSPROP) || (cfg->opt & MONO_OPT_COPYPROP)) {
3785                 if (cfg->comp_done & MONO_COMP_SSA && !COMPILE_LLVM (cfg)) {
3786 #ifndef DISABLE_SSA
3787                         mono_ssa_cprop (cfg);
3788 #endif
3789                 }
3790         }
3791
3792 #ifndef DISABLE_SSA
3793         if (cfg->comp_done & MONO_COMP_SSA && !COMPILE_LLVM (cfg)) {
3794                 //mono_ssa_strength_reduction (cfg);
3795
3796                 if (cfg->opt & MONO_OPT_DEADCE)
3797                         mono_ssa_deadce (cfg);
3798
3799                 if ((cfg->flags & (MONO_CFG_HAS_LDELEMA|MONO_CFG_HAS_CHECK_THIS)) && (cfg->opt & MONO_OPT_ABCREM))
3800                         mono_perform_abc_removal (cfg);
3801
3802                 mono_ssa_remove (cfg);
3803                 mono_local_cprop (cfg);
3804                 mono_handle_global_vregs (cfg);
3805                 if (cfg->opt & MONO_OPT_DEADCE)
3806                         mono_local_deadce (cfg);
3807
3808                 if (cfg->opt & MONO_OPT_BRANCH)
3809                         mono_optimize_branches (cfg);
3810         }
3811 #endif
3812
3813         if (cfg->comp_done & MONO_COMP_SSA && COMPILE_LLVM (cfg)) {
3814                 mono_ssa_loop_invariant_code_motion (cfg);
3815                 /* This removes MONO_INST_FAULT flags too so perform it unconditionally */
3816                 if (cfg->opt & MONO_OPT_ABCREM)
3817                         mono_perform_abc_removal (cfg);
3818         }
3819
3820         /* after SSA removal */
3821         if (parts == 3) {
3822                 if (MONO_METHOD_COMPILE_END_ENABLED ())
3823                         MONO_PROBE_METHOD_COMPILE_END (method, TRUE);
3824                 return cfg;
3825         }
3826
3827 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
3828         if (COMPILE_SOFT_FLOAT (cfg))
3829                 mono_decompose_soft_float (cfg);
3830 #endif
3831         if (COMPILE_LLVM (cfg))
3832                 mono_decompose_vtype_opts_llvm (cfg);
3833         else
3834                 mono_decompose_vtype_opts (cfg);
3835         if (cfg->flags & MONO_CFG_HAS_ARRAY_ACCESS)
3836                 mono_decompose_array_access_opts (cfg);
3837
3838         if (cfg->got_var) {
3839 #ifndef MONO_ARCH_GOT_REG
3840                 GList *regs;
3841 #endif
3842                 int got_reg;
3843
3844                 g_assert (cfg->got_var_allocated);
3845
3846                 /* 
3847                  * Allways allocate the GOT var to a register, because keeping it
3848                  * in memory will increase the number of live temporaries in some
3849                  * code created by inssel.brg, leading to the well known spills+
3850                  * branches problem. Testcase: mcs crash in 
3851                  * System.MonoCustomAttrs:GetCustomAttributes.
3852                  */
3853 #ifdef MONO_ARCH_GOT_REG
3854                 got_reg = MONO_ARCH_GOT_REG;
3855 #else
3856                 regs = mono_arch_get_global_int_regs (cfg);
3857                 g_assert (regs);
3858                 got_reg = GPOINTER_TO_INT (regs->data);
3859                 g_list_free (regs);
3860 #endif
3861                 cfg->got_var->opcode = OP_REGVAR;
3862                 cfg->got_var->dreg = got_reg;
3863                 cfg->used_int_regs |= 1LL << cfg->got_var->dreg;
3864         }
3865
3866         /*
3867          * Have to call this again to process variables added since the first call.
3868          */
3869         mono_liveness_handle_exception_clauses (cfg);
3870
3871         if (cfg->opt & MONO_OPT_LINEARS) {
3872                 GList *vars, *regs, *l;
3873                 
3874                 /* fixme: maybe we can avoid to compute livenesss here if already computed ? */
3875                 cfg->comp_done &= ~MONO_COMP_LIVENESS;
3876                 if (!(cfg->comp_done & MONO_COMP_LIVENESS))
3877                         mono_analyze_liveness (cfg);
3878
3879                 if ((vars = mono_arch_get_allocatable_int_vars (cfg))) {
3880                         regs = mono_arch_get_global_int_regs (cfg);
3881                         /* Remove the reg reserved for holding the GOT address */
3882                         if (cfg->got_var) {
3883                                 for (l = regs; l; l = l->next) {
3884                                         if (GPOINTER_TO_UINT (l->data) == cfg->got_var->dreg) {
3885                                                 regs = g_list_delete_link (regs, l);
3886                                                 break;
3887                                         }
3888                                 }
3889                         }
3890                         mono_linear_scan (cfg, vars, regs, &cfg->used_int_regs);
3891                 }
3892         }
3893
3894         //mono_print_code (cfg, "");
3895
3896     //print_dfn (cfg);
3897         
3898         /* variables are allocated after decompose, since decompose could create temps */
3899         if (!COMPILE_LLVM (cfg)) {
3900                 mono_arch_allocate_vars (cfg);
3901                 if (cfg->exception_type)
3902                         return cfg;
3903         }
3904
3905         {
3906                 MonoBasicBlock *bb;
3907                 gboolean need_local_opts;
3908
3909                 if (!COMPILE_LLVM (cfg)) {
3910                         mono_spill_global_vars (cfg, &need_local_opts);
3911
3912                         if (need_local_opts || cfg->compile_aot) {
3913                                 /* To optimize code created by spill_global_vars */
3914                                 mono_local_cprop (cfg);
3915                                 if (cfg->opt & MONO_OPT_DEADCE)
3916                                         mono_local_deadce (cfg);
3917                         }
3918                 }
3919
3920                 /* Add branches between non-consecutive bblocks */
3921                 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
3922                         if (bb->last_ins && MONO_IS_COND_BRANCH_OP (bb->last_ins) &&
3923                                 bb->last_ins->inst_false_bb && bb->next_bb != bb->last_ins->inst_false_bb) {
3924                                 /* we are careful when inverting, since bugs like #59580
3925                                  * could show up when dealing with NaNs.
3926                                  */
3927                                 if (MONO_IS_COND_BRANCH_NOFP(bb->last_ins) && bb->next_bb == bb->last_ins->inst_true_bb) {
3928                                         MonoBasicBlock *tmp =  bb->last_ins->inst_true_bb;
3929                                         bb->last_ins->inst_true_bb = bb->last_ins->inst_false_bb;
3930                                         bb->last_ins->inst_false_bb = tmp;
3931
3932                                         bb->last_ins->opcode = mono_reverse_branch_op (bb->last_ins->opcode);
3933                                 } else {                        
3934                                         MonoInst *inst = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst));
3935                                         inst->opcode = OP_BR;
3936                                         inst->inst_target_bb = bb->last_ins->inst_false_bb;
3937                                         mono_bblock_add_inst (bb, inst);
3938                                 }
3939                         }
3940                 }
3941
3942                 if (cfg->verbose_level >= 4) {
3943                         for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
3944                                 MonoInst *tree = bb->code;      
3945                                 g_print ("DUMP BLOCK %d:\n", bb->block_num);
3946                                 if (!tree)
3947                                         continue;
3948                                 for (; tree; tree = tree->next) {
3949                                         mono_print_ins_index (-1, tree);
3950                                 }
3951                         }
3952                 }
3953
3954                 /* FIXME: */
3955                 for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
3956                         bb->max_vreg = cfg->next_vreg;
3957                 }
3958         }
3959
3960         if (COMPILE_LLVM (cfg)) {
3961 #ifdef ENABLE_LLVM
3962                 char *nm;
3963
3964                 /* The IR has to be in SSA form for LLVM */
3965                 if (!(cfg->comp_done & MONO_COMP_SSA)) {
3966                         cfg->exception_message = g_strdup ("SSA disabled.");
3967                         cfg->disable_llvm = TRUE;
3968                 }
3969
3970                 if (cfg->flags & MONO_CFG_HAS_ARRAY_ACCESS)
3971                         mono_decompose_array_access_opts (cfg);
3972
3973                 if (!cfg->disable_llvm)
3974                         mono_llvm_emit_method (cfg);
3975                 if (cfg->disable_llvm) {
3976                         if (cfg->verbose_level >= cfg->llvm_only ? 0 : 1) {
3977                                 //nm = mono_method_full_name (cfg->method, TRUE);
3978                                 printf ("LLVM failed for '%s': %s\n", method->name, cfg->exception_message);
3979                                 //g_free (nm);
3980                         }
3981                         if (cfg->llvm_only) {
3982                                 cfg->disable_aot = TRUE;
3983                                 return cfg;
3984                         }
3985                         mono_destroy_compile (cfg);
3986                         try_llvm = FALSE;
3987                         goto restart_compile;
3988                 }
3989
3990                 if (cfg->verbose_level > 0 && !cfg->compile_aot) {
3991                         nm = mono_method_full_name (cfg->method, TRUE);
3992                         g_print ("LLVM Method %s emitted at %p to %p (code length %d) [%s]\n", 
3993                                          nm, 
3994                                          cfg->native_code, cfg->native_code + cfg->code_len, cfg->code_len, cfg->domain->friendly_name);
3995                         g_free (nm);
3996                 }
3997 #endif
3998         } else {
3999                 mono_codegen (cfg);
4000         }
4001
4002         if (COMPILE_LLVM (cfg))
4003                 InterlockedIncrement (&mono_jit_stats.methods_with_llvm);
4004         else
4005                 InterlockedIncrement (&mono_jit_stats.methods_without_llvm);
4006
4007         cfg->jit_info = create_jit_info (cfg, method_to_compile);
4008
4009 #ifdef MONO_ARCH_HAVE_LIVERANGE_OPS
4010         if (cfg->extend_live_ranges) {
4011                 /* Extend live ranges to cover the whole method */
4012                 for (i = 0; i < cfg->num_varinfo; ++i)
4013                         MONO_VARINFO (cfg, i)->live_range_end = cfg->code_len;
4014         }
4015 #endif
4016
4017         if (!cfg->compile_aot)
4018                 mono_save_xdebug_info (cfg);
4019
4020         mini_gc_create_gc_map (cfg);
4021  
4022         mono_save_seq_point_info (cfg);
4023
4024         if (cfg->verbose_level >= 2) {
4025                 char *id =  mono_method_full_name (cfg->method, FALSE);
4026                 mono_disassemble_code (cfg, cfg->native_code, cfg->code_len, id + 3);
4027                 g_free (id);
4028         }
4029
4030         if (!cfg->compile_aot) {
4031                 mono_domain_lock (cfg->domain);
4032                 mono_jit_info_table_add (cfg->domain, cfg->jit_info);
4033
4034                 if (cfg->method->dynamic)
4035                         mono_dynamic_code_hash_lookup (cfg->domain, cfg->method)->ji = cfg->jit_info;
4036                 mono_domain_unlock (cfg->domain);
4037         }
4038
4039 #if 0
4040         if (cfg->gsharedvt)
4041                 printf ("GSHAREDVT: %s\n", mono_method_full_name (cfg->method, TRUE));
4042 #endif
4043
4044         /* collect statistics */
4045 #ifndef DISABLE_PERFCOUNTERS
4046         mono_perfcounters->jit_methods++;
4047         mono_perfcounters->jit_bytes += header->code_size;
4048 #endif
4049         mono_jit_stats.allocated_code_size += cfg->code_len;
4050         code_size_ratio = cfg->code_len;
4051         if (code_size_ratio > mono_jit_stats.biggest_method_size && mono_jit_stats.enabled) {
4052                 mono_jit_stats.biggest_method_size = code_size_ratio;
4053                 g_free (mono_jit_stats.biggest_method);
4054                 mono_jit_stats.biggest_method = g_strdup_printf ("%s::%s)", method->klass->name, method->name);
4055         }
4056         code_size_ratio = (code_size_ratio * 100) / header->code_size;
4057         if (code_size_ratio > mono_jit_stats.max_code_size_ratio && mono_jit_stats.enabled) {
4058                 mono_jit_stats.max_code_size_ratio = code_size_ratio;
4059                 g_free (mono_jit_stats.max_ratio_method);
4060                 mono_jit_stats.max_ratio_method = g_strdup_printf ("%s::%s)", method->klass->name, method->name);
4061         }
4062         mono_jit_stats.native_code_size += cfg->code_len;
4063
4064         if (MONO_METHOD_COMPILE_END_ENABLED ())
4065                 MONO_PROBE_METHOD_COMPILE_END (method, TRUE);
4066
4067         return cfg;
4068 }
4069
4070 void*
4071 mono_arch_instrument_epilog (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments)
4072 {
4073         return mono_arch_instrument_epilog_full (cfg, func, p, enable_arguments, FALSE);
4074 }
4075
4076 void
4077 mono_cfg_add_try_hole (MonoCompile *cfg, MonoExceptionClause *clause, guint8 *start, MonoBasicBlock *bb)
4078 {
4079         TryBlockHole *hole = mono_mempool_alloc (cfg->mempool, sizeof (TryBlockHole));
4080         hole->clause = clause;
4081         hole->start_offset = start - cfg->native_code;
4082         hole->basic_block = bb;
4083
4084         cfg->try_block_holes = g_slist_append_mempool (cfg->mempool, cfg->try_block_holes, hole);
4085 }
4086
4087 void
4088 mono_cfg_set_exception (MonoCompile *cfg, int type)
4089 {
4090         cfg->exception_type = type;
4091 }
4092
4093 #endif /* DISABLE_JIT */
4094
4095 static MonoJitInfo*
4096 create_jit_info_for_trampoline (MonoMethod *wrapper, MonoTrampInfo *info)
4097 {
4098         MonoDomain *domain = mono_get_root_domain ();
4099         MonoJitInfo *jinfo;
4100         guint8 *uw_info;
4101         guint32 info_len;
4102
4103         if (info->uw_info) {
4104                 uw_info = info->uw_info;
4105                 info_len = info->uw_info_len;
4106         } else {
4107                 uw_info = mono_unwind_ops_encode (info->unwind_ops, &info_len);
4108         }
4109
4110         jinfo = mono_domain_alloc0 (domain, MONO_SIZEOF_JIT_INFO);
4111         jinfo->d.method = wrapper;
4112         jinfo->code_start = info->code;
4113         jinfo->code_size = info->code_size;
4114         jinfo->unwind_info = mono_cache_unwind_info (uw_info, info_len);
4115
4116         if (!info->uw_info)
4117                 g_free (uw_info);
4118
4119         return jinfo;
4120 }
4121
4122 /*
4123  * mono_jit_compile_method_inner:
4124  *
4125  *   Main entry point for the JIT.
4126  */
4127 gpointer
4128 mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, int opt, MonoException **jit_ex)
4129 {
4130         MonoCompile *cfg;
4131         gpointer code = NULL;
4132         MonoJitInfo *jinfo, *info;
4133         MonoVTable *vtable;
4134         MonoException *ex = NULL;
4135         guint32 prof_options;
4136         GTimer *jit_timer;
4137         MonoMethod *prof_method, *shared;
4138
4139         if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
4140             (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
4141                 MonoMethod *nm;
4142                 MonoMethodPInvoke* piinfo = (MonoMethodPInvoke *) method;
4143
4144                 if (!piinfo->addr) {
4145                         if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
4146                                 piinfo->addr = mono_lookup_internal_call (method);
4147                         else if (method->iflags & METHOD_IMPL_ATTRIBUTE_NATIVE)
4148 #ifdef HOST_WIN32
4149                                 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);
4150 #else
4151                                 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);
4152 #endif
4153                         else
4154                                 mono_lookup_pinvoke_call (method, NULL, NULL);
4155                 }
4156                 nm = mono_marshal_get_native_wrapper (method, TRUE, mono_aot_only);
4157                 code = mono_get_addr_from_ftnptr (mono_compile_method (nm));
4158                 jinfo = mono_jit_info_table_find (target_domain, code);
4159                 if (!jinfo)
4160                         jinfo = mono_jit_info_table_find (mono_domain_get (), code);
4161                 if (jinfo)
4162                         mono_profiler_method_end_jit (method, jinfo, MONO_PROFILE_OK);
4163                 return code;
4164         } else if ((method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
4165                 const char *name = method->name;
4166                 char *full_name, *msg;
4167                 MonoMethod *nm;
4168
4169                 if (method->klass->parent == mono_defaults.multicastdelegate_class) {
4170                         if (*name == '.' && (strcmp (name, ".ctor") == 0)) {
4171                                 MonoJitICallInfo *mi = mono_find_jit_icall_by_name ("mono_delegate_ctor");
4172                                 g_assert (mi);
4173                                 /*
4174                                  * We need to make sure this wrapper
4175                                  * is compiled because it might end up
4176                                  * in an (M)RGCTX if generic sharing
4177                                  * is enabled, and would be called
4178                                  * indirectly.  If it were a
4179                                  * trampoline we'd try to patch that
4180                                  * indirect call, which is not
4181                                  * possible.
4182                                  */
4183                                 return mono_get_addr_from_ftnptr ((gpointer)mono_icall_get_wrapper_full (mi, TRUE));
4184                         } else if (*name == 'I' && (strcmp (name, "Invoke") == 0)) {
4185                                 if (mono_llvm_only) {
4186                                         nm = mono_marshal_get_delegate_invoke (method, NULL);
4187                                         return mono_get_addr_from_ftnptr (mono_compile_method (nm));
4188                                 }
4189                                 return mono_create_delegate_trampoline (target_domain, method->klass);
4190                         } else if (*name == 'B' && (strcmp (name, "BeginInvoke") == 0)) {
4191                                 nm = mono_marshal_get_delegate_begin_invoke (method);
4192                                 return mono_get_addr_from_ftnptr (mono_compile_method (nm));
4193                         } else if (*name == 'E' && (strcmp (name, "EndInvoke") == 0)) {
4194                                 nm = mono_marshal_get_delegate_end_invoke (method);
4195                                 return mono_get_addr_from_ftnptr (mono_compile_method (nm));
4196                         }
4197                 }
4198
4199                 full_name = mono_method_full_name (method, TRUE);
4200                 msg = g_strdup_printf ("Unrecognizable runtime implemented method '%s'", full_name);
4201                 *jit_ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", msg);
4202                 g_free (full_name);
4203                 g_free (msg);
4204                 return NULL;
4205         }
4206
4207         if (method->wrapper_type == MONO_WRAPPER_UNKNOWN) {
4208                 WrapperInfo *info = mono_marshal_get_wrapper_info (method);
4209
4210                 if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN || info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_OUT) {
4211                         static MonoTrampInfo *in_tinfo, *out_tinfo;
4212                         MonoTrampInfo *tinfo;
4213                         MonoJitInfo *jinfo;
4214                         gboolean is_in = info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN;
4215
4216                         if (is_in && in_tinfo)
4217                                 return in_tinfo->code;
4218                         else if (!is_in && out_tinfo)
4219                                 return out_tinfo->code;
4220
4221                         /*
4222                          * This is a special wrapper whose body is implemented in assembly, like a trampoline. We use a wrapper so EH
4223                          * works.
4224                          * FIXME: The caller signature doesn't match the callee, which might cause problems on some platforms
4225                          */
4226                         if (mono_aot_only)
4227                                 mono_aot_get_trampoline_full (is_in ? "gsharedvt_trampoline" : "gsharedvt_out_trampoline", &tinfo);
4228                         else
4229                                 mono_arch_get_gsharedvt_trampoline (&tinfo, FALSE);
4230                         jinfo = create_jit_info_for_trampoline (method, tinfo);
4231                         mono_jit_info_table_add (mono_get_root_domain (), jinfo);
4232                         if (is_in)
4233                                 in_tinfo = tinfo;
4234                         else
4235                                 out_tinfo = tinfo;
4236                         return tinfo->code;
4237                 }
4238         }
4239
4240         if (mono_aot_only) {
4241                 char *fullname = mono_method_full_name (method, TRUE);
4242                 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);
4243
4244                 *jit_ex = mono_get_exception_execution_engine (msg);
4245                 g_free (fullname);
4246                 g_free (msg);
4247                 
4248                 return NULL;
4249         }
4250
4251         jit_timer = g_timer_new ();
4252
4253         cfg = mini_method_compile (method, opt, target_domain, JIT_FLAG_RUN_CCTORS, 0, -1);
4254         prof_method = cfg->method;
4255
4256         g_timer_stop (jit_timer);
4257         mono_jit_stats.jit_time += g_timer_elapsed (jit_timer, NULL);
4258         g_timer_destroy (jit_timer);
4259
4260         switch (cfg->exception_type) {
4261         case MONO_EXCEPTION_NONE:
4262                 break;
4263         case MONO_EXCEPTION_TYPE_LOAD:
4264         case MONO_EXCEPTION_MISSING_FIELD:
4265         case MONO_EXCEPTION_MISSING_METHOD:
4266         case MONO_EXCEPTION_FILE_NOT_FOUND:
4267         case MONO_EXCEPTION_BAD_IMAGE: {
4268                 /* Throw a type load exception if needed */
4269                 MonoLoaderError *error = mono_loader_get_last_error ();
4270
4271                 if (error) {
4272                         ex = mono_loader_error_prepare_exception (error);
4273                 } else {
4274                         if (cfg->exception_ptr) {
4275                                 ex = mono_class_get_exception_for_failure (cfg->exception_ptr);
4276                         } else {
4277                                 if (cfg->exception_type == MONO_EXCEPTION_MISSING_FIELD)
4278                                         ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingFieldException", cfg->exception_message);
4279                                 else if (cfg->exception_type == MONO_EXCEPTION_MISSING_METHOD)
4280                                         ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MissingMethodException", cfg->exception_message);
4281                                 else if (cfg->exception_type == MONO_EXCEPTION_TYPE_LOAD)
4282                                         ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "TypeLoadException", cfg->exception_message);
4283                                 else if (cfg->exception_type == MONO_EXCEPTION_FILE_NOT_FOUND)
4284                                         ex = mono_exception_from_name_msg (mono_defaults.corlib, "System.IO", "FileNotFoundException", cfg->exception_message);
4285                                 else if (cfg->exception_type == MONO_EXCEPTION_BAD_IMAGE)
4286                                         ex = mono_get_exception_bad_image_format (cfg->exception_message);
4287                                 else
4288                                         g_assert_not_reached ();
4289                         }
4290                 }
4291                 break;
4292         }
4293         case MONO_EXCEPTION_INVALID_PROGRAM:
4294                 ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", cfg->exception_message);
4295                 break;
4296         case MONO_EXCEPTION_UNVERIFIABLE_IL:
4297                 ex = mono_exception_from_name_msg (mono_defaults.corlib, "System.Security", "VerificationException", cfg->exception_message);
4298                 break;
4299         case MONO_EXCEPTION_METHOD_ACCESS:
4300                 ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "MethodAccessException", cfg->exception_message);
4301                 break;
4302         case MONO_EXCEPTION_FIELD_ACCESS:
4303                 ex = mono_exception_from_name_msg (mono_defaults.corlib, "System", "FieldAccessException", cfg->exception_message);
4304                 break;
4305         case MONO_EXCEPTION_OBJECT_SUPPLIED: {
4306                 MonoException *exp = cfg->exception_ptr;
4307                 MONO_GC_UNREGISTER_ROOT (cfg->exception_ptr);
4308
4309                 ex = exp;
4310                 break;
4311         }
4312         case MONO_EXCEPTION_OUT_OF_MEMORY:
4313                 ex = mono_domain_get ()->out_of_memory_ex;
4314                 break;
4315         case MONO_EXCEPTION_MONO_ERROR:
4316                 g_assert (!mono_error_ok (&cfg->error));
4317                 ex = mono_error_convert_to_exception (&cfg->error);
4318                 break;
4319         default:
4320                 g_assert_not_reached ();
4321         }
4322
4323         if (ex) {
4324                 if (cfg->prof_options & MONO_PROFILE_JIT_COMPILATION)
4325                         mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_FAILED);
4326
4327                 mono_destroy_compile (cfg);
4328                 *jit_ex = ex;
4329
4330                 return NULL;
4331         }
4332
4333         if (mono_method_is_generic_sharable (method, FALSE))
4334                 shared = mini_get_shared_method (method);
4335         else
4336                 shared = NULL;
4337
4338         mono_domain_lock (target_domain);
4339
4340         /* Check if some other thread already did the job. In this case, we can
4341        discard the code this thread generated. */
4342
4343         info = mini_lookup_method (target_domain, method, shared);
4344         if (info) {
4345                 /* We can't use a domain specific method in another domain */
4346                 if ((target_domain == mono_domain_get ()) || info->domain_neutral) {
4347                         code = info->code_start;
4348 //                      printf("Discarding code for method %s\n", method->name);
4349                 }
4350         }
4351         if (code == NULL) {
4352                 /* The lookup + insert is atomic since this is done inside the domain lock */
4353                 mono_domain_jit_code_hash_lock (target_domain);
4354                 mono_internal_hash_table_insert (&target_domain->jit_code_hash, cfg->jit_info->d.method, cfg->jit_info);
4355                 mono_domain_jit_code_hash_unlock (target_domain);
4356
4357                 code = cfg->native_code;
4358
4359                 if (cfg->gshared && mono_method_is_generic_sharable (method, FALSE))
4360                         mono_stats.generics_shared_methods++;
4361                 if (cfg->gsharedvt)
4362                         mono_stats.gsharedvt_methods++;
4363         }
4364
4365         jinfo = cfg->jit_info;
4366
4367         prof_options = cfg->prof_options;
4368
4369         /*
4370          * Update global stats while holding a lock, instead of doing many
4371          * InterlockedIncrement operations during JITting.
4372          */
4373         mono_jit_stats.allocate_var += cfg->stat_allocate_var;
4374         mono_jit_stats.locals_stack_size += cfg->stat_locals_stack_size;
4375         mono_jit_stats.basic_blocks += cfg->stat_basic_blocks;
4376         mono_jit_stats.max_basic_blocks = MAX (cfg->stat_basic_blocks, mono_jit_stats.max_basic_blocks);
4377         mono_jit_stats.cil_code_size += cfg->stat_cil_code_size;
4378         mono_jit_stats.regvars += cfg->stat_n_regvars;
4379         mono_jit_stats.inlineable_methods += cfg->stat_inlineable_methods;
4380         mono_jit_stats.inlined_methods += cfg->stat_inlined_methods;
4381         mono_jit_stats.code_reallocs += cfg->stat_code_reallocs;
4382
4383         mono_destroy_compile (cfg);
4384
4385 #ifndef DISABLE_JIT
4386         if (domain_jit_info (target_domain)->jump_target_hash) {
4387                 MonoJumpInfo patch_info;
4388                 MonoJumpList *jlist;
4389                 GSList *tmp;
4390                 jlist = g_hash_table_lookup (domain_jit_info (target_domain)->jump_target_hash, method);
4391                 if (jlist) {
4392                         patch_info.next = NULL;
4393                         patch_info.ip.i = 0;
4394                         patch_info.type = MONO_PATCH_INFO_METHOD_JUMP;
4395                         patch_info.data.method = method;
4396                         g_hash_table_remove (domain_jit_info (target_domain)->jump_target_hash, method);
4397
4398 #if defined(__native_client_codegen__) && defined(__native_client__)
4399                         /* These patches are applied after a method has been installed, no target munging is needed. */
4400                         nacl_allow_target_modification (FALSE);
4401 #endif
4402 #ifdef MONO_ARCH_HAVE_PATCH_CODE_NEW
4403                         for (tmp = jlist->list; tmp; tmp = tmp->next) {
4404                                 gpointer target = mono_resolve_patch_target (NULL, target_domain, tmp->data, &patch_info, TRUE);
4405                                 mono_arch_patch_code_new (NULL, target_domain, tmp->data, &patch_info, target);
4406                         }
4407 #else
4408                         for (tmp = jlist->list; tmp; tmp = tmp->next)
4409                                 mono_arch_patch_code (NULL, NULL, target_domain, tmp->data, &patch_info, TRUE);
4410 #endif
4411 #if defined(__native_client_codegen__) && defined(__native_client__)
4412                         nacl_allow_target_modification (TRUE);
4413 #endif
4414                 }
4415         }
4416
4417         mono_emit_jit_map (jinfo);
4418 #endif
4419         mono_domain_unlock (target_domain);
4420
4421         vtable = mono_class_vtable (target_domain, method->klass);
4422         if (!vtable) {
4423                 ex = mono_class_get_exception_for_failure (method->klass);
4424                 g_assert (ex);
4425                 *jit_ex = ex;
4426                 return NULL;
4427         }
4428
4429         if (prof_options & MONO_PROFILE_JIT_COMPILATION) {
4430                 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
4431                         if (mono_marshal_method_from_wrapper (method)) {
4432                                 /* Native func wrappers have no method */
4433                                 /* The profiler doesn't know about wrappers, so pass the original icall method */
4434                                 mono_profiler_method_end_jit (mono_marshal_method_from_wrapper (method), jinfo, MONO_PROFILE_OK);
4435                         }
4436                 }
4437                 mono_profiler_method_end_jit (method, jinfo, MONO_PROFILE_OK);
4438                 if (prof_method != method) {
4439                         mono_profiler_method_end_jit (prof_method, jinfo, MONO_PROFILE_OK);
4440                 }
4441         }
4442
4443         ex = mono_runtime_class_init_full (vtable, FALSE);
4444         if (ex) {
4445                 *jit_ex = ex;
4446                 return NULL;
4447         }
4448         return code;
4449 }
4450
4451 /*
4452  * mini_get_underlying_type:
4453  *
4454  *   Return the type the JIT will use during compilation.
4455  * Handles: byref, enums, native types, generic sharing.
4456  * For gsharedvt types, it will return the original VAR/MVAR.
4457  */
4458 MonoType*
4459 mini_get_underlying_type (MonoType *type)
4460 {
4461         return mini_type_get_underlying_type (type);
4462 }
4463
4464 void
4465 mini_jit_init (void)
4466 {
4467         mono_mutex_init_recursive (&jit_mutex);
4468 #ifndef DISABLE_JIT
4469         current_backend = g_new0 (MonoBackend, 1);
4470         init_backend (current_backend);
4471 #endif
4472 }
4473
4474 void
4475 mini_jit_cleanup (void)
4476 {
4477 #ifndef DISABLE_JIT
4478         g_free (emul_opcode_map);
4479         g_free (emul_opcode_opcodes);
4480 #endif
4481 }
4482
4483 #ifndef ENABLE_LLVM
4484 void
4485 mono_llvm_emit_aot_file_info (MonoAotFileInfo *info, gboolean has_jitted_code)
4486 {
4487         g_assert_not_reached ();
4488 }
4489
4490 void mono_llvm_emit_aot_data (const char *symbol, guint8 *data, int data_len)
4491 {
4492         g_assert_not_reached ();
4493 }
4494
4495 #endif
4496
4497 #if !defined(ENABLE_LLVM_RUNTIME) && !defined(ENABLE_LLVM)
4498
4499 void
4500 mono_llvm_cpp_throw_exception (void)
4501 {
4502         g_assert_not_reached ();
4503 }
4504
4505 #endif
4506
4507 #ifdef DISABLE_JIT
4508
4509 MonoCompile*
4510 mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFlags flags, int parts, int aot_method_index)
4511 {
4512         g_assert_not_reached ();
4513         return NULL;
4514 }
4515
4516 void
4517 mono_destroy_compile (MonoCompile *cfg)
4518 {
4519         g_assert_not_reached ();
4520 }
4521
4522 void
4523 mono_add_patch_info (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target)
4524 {
4525         g_assert_not_reached ();
4526 }
4527
4528 #endif /* DISABLE_JIT */