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