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