2002-06-18 Dietmar Maurer <dietmar@ximian.com>
[mono.git] / mono / jit / jit.c
1 /*
2  * jit.c: The mono JIT compiler.
3  *
4  * Author:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *
7  * (C) 2001 Ximian, Inc.
8  */
9
10 #include <config.h>
11 #if HAVE_BOEHM_GC
12 #include <gc/gc.h>
13 #endif
14 #include <glib.h>
15 #include <stdlib.h>
16 #include <stdarg.h>
17 #include <string.h>
18 #include <unistd.h>
19
20 #include <mono/metadata/verify.h>
21 #include <mono/metadata/assembly.h>
22 #include <mono/metadata/loader.h>
23 #include <mono/metadata/cil-coff.h>
24 #include <mono/metadata/tabledefs.h>
25 #include <mono/metadata/class.h>
26 #include <mono/metadata/object.h>
27 #include <mono/metadata/debug-helpers.h>
28 #include <mono/metadata/opcodes.h>
29 #include <mono/metadata/mono-endian.h>
30 #include <mono/metadata/tokentype.h>
31 #include <mono/metadata/threads.h>
32 #include <mono/metadata/socket-io.h>
33 #include <mono/metadata/appdomain.h>
34 #include <mono/arch/x86/x86-codegen.h>
35 #include <mono/io-layer/io-layer.h>
36 #include <mono/metadata/profiler-private.h>
37
38 #include "jit.h"
39 #include "helpers.h"
40 #include "regset.h"
41 #include "codegen.h"
42 #include "debug.h"
43
44 /* 
45  * if OPT_BOOL is defined we use 32bit to store boolean local variables.  This
46  * gives great speedup for boolean expressions, but unfortunately it changes
47  * semantics, so i disable it until we have a real solution  */
48 /* #define OPT_BOOL */
49
50 #define MAKE_CJUMP(name)                                                      \
51 case CEE_##name:                                                              \
52 case CEE_##name##_S: {                                                        \
53         gint32 target;                                                        \
54         int near_jump = *ip == CEE_##name##_S;                                \
55         ++ip;                                                                 \
56         sp -= 2;                                                              \
57         t1 = mono_ctree_new (mp, MB_TERM_COMPARE, sp [0], sp [1]);            \
58         t1 = mono_ctree_new (mp, MB_TERM_CBRANCH, t1, NULL);                  \
59         if (near_jump)                                                        \
60                 target = cli_addr + 2 + (signed char) *ip;                    \
61         else                                                                  \
62                 target = cli_addr + 5 + (gint32) read32 (ip);                 \
63         g_assert (target >= 0 && target <= header->code_size);                \
64         g_assert (bcinfo [target].is_block_start);                            \
65         tbb = &cfg->bblocks [bcinfo [target].block_id];                       \
66         create_outstack (cfg, bb, stack, sp - stack);                         \
67         mark_reached (cfg, tbb, bb->outstack, bb->outdepth);                  \
68         t1->data.bi.target = tbb;                                             \
69         t1->data.bi.cond = CEE_##name;                                        \
70         ADD_TREE (t1, cli_addr);                                              \
71         ip += near_jump ? 1: 4;                                               \
72         break;                                                                \
73 }
74
75 #define MAKE_BI_ALU(name)                                                     \
76 case CEE_##name: {                                                            \
77         ++ip;                                                                 \
78         sp -= 2;                                                              \
79         t1 = mono_ctree_new (mp, MB_TERM_##name, sp [0], sp [1]);             \
80         PUSH_TREE (t1, sp [0]->svt);                                          \
81         break;                                                                \
82 }
83
84 #ifndef ARCH_X86
85 #define MAKE_SPILLED_BI_ALU1(name, s1, s2) {                                  \
86         t1 = mono_ctree_new (mp, MB_TERM_##name, s1, s2);                     \
87         PUSH_TREE (t1, s1->svt); }                                            
88 #else
89 #define MAKE_SPILLED_BI_ALU1(name, s1, s2)                                    \
90         t1 = mono_ctree_new (mp, MB_TERM_##name, s1, s2);                     \
91         t1->svt = s1->svt;                                                    \
92         t1 = mono_store_tree (cfg, -1, t1, &t2);                              \
93         g_assert (t1);                                                        \
94         ADD_TREE (t1, cli_addr);                                              \
95         PUSH_TREE (t2, t2->svt);                                              
96 #endif
97
98 #define MAKE_CMP(cname)                                                       \
99 case CEE_##cname: {                                                           \
100         ++ip;                                                                 \
101         sp -= 2;                                                              \
102         t1 = mono_ctree_new (mp, MB_TERM_COMPARE, sp [0], sp [1]);            \
103         t1 = mono_ctree_new (mp, MB_TERM_CSET, t1, NULL);                     \
104         t1->data.i = CEE_##cname;                                             \
105         PUSH_TREE (t1, VAL_I32);                                              \
106         break;                                                                \
107 }
108
109 #define MAKE_SPILLED_BI_ALU(name)                                             \
110 case CEE_##name: {                                                            \
111         ++ip;                                                                 \
112         sp -= 2;                                                              \
113         MAKE_SPILLED_BI_ALU1 (name, sp [0], sp [1])                           \
114         break;                                                                \
115 }
116
117 #define MAKE_LDIND(name, op, svt)                                             \
118 case CEE_##name: {                                                            \
119         ++ip;                                                                 \
120         sp--;                                                                 \
121         t1 = mono_ctree_new (mp, op, *sp, NULL);                              \
122         PUSH_TREE (t1, svt);                                                  \
123         break;                                                                \
124 }
125         
126 #define MAKE_LDELEM(name, op, svt, s)                                         \
127 case CEE_##name: {                                                            \
128         ++ip;                                                                 \
129         sp -= 2;                                                              \
130         t1 = mono_ctree_new (mp, MB_TERM_LDELEMA, sp [0], sp [1]);            \
131         t1->data.i = s;                                                       \
132         t1 = mono_ctree_new (mp, op, t1, NULL);                               \
133         PUSH_TREE (t1, svt);                                                  \
134         break;                                                                \
135 }
136
137 #define MAKE_LDELEM_OLD(name, op, svt, s)                                     \
138 case CEE_##name: {                                                            \
139         ++ip;                                                                 \
140         sp -= 2;                                                              \
141         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);                      \
142         t1->data.i = s;                                                       \
143         t1 = mono_ctree_new (mp, MB_TERM_MUL, sp [1], t1);                    \
144         t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);                      \
145         t2->data.i = G_STRUCT_OFFSET (MonoArray, vector);                     \
146         t2 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t2);                    \
147         t1 = mono_ctree_new (mp, MB_TERM_ADD, t1, t2);                        \
148         t1 = mono_ctree_new (mp, op, t1, NULL);                               \
149         PUSH_TREE (t1, svt);                                                  \
150         break;                                                                \
151 }
152         
153 #define MAKE_STIND(name, op)                                                  \
154 case CEE_##name: {                                                            \
155         ++ip;                                                                 \
156         sp -= 2;                                                              \
157         t1 = mono_ctree_new (mp, op, sp [0], sp [1]);                         \
158         ADD_TREE (t1, cli_addr);                                              \
159         break;                                                                \
160 }
161
162 #define MAKE_STELEM(name, op, s)                                              \
163 case CEE_##name: {                                                            \
164         ++ip;                                                                 \
165         sp -= 3;                                                              \
166         t1 = mono_ctree_new (mp, MB_TERM_LDELEMA, sp [0], sp [1]);            \
167         t1->data.i = s;                                                       \
168         t1 = mono_ctree_new (mp, op, t1, sp [2]);                             \
169         ADD_TREE (t1, cli_addr);                                              \
170         break;                                                                \
171 }
172         
173 #define MAKE_STELEM_OLD(name, op, s)                                          \
174 case CEE_##name: {                                                            \
175         ++ip;                                                                 \
176         sp -= 3;                                                              \
177         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);                      \
178         t1->data.i = s;                                                       \
179         t1 = mono_ctree_new (mp, MB_TERM_MUL, sp [1], t1);                    \
180         t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);                      \
181         t2->data.i = G_STRUCT_OFFSET (MonoArray, vector);                     \
182         t2 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t2);                    \
183         t1 = mono_ctree_new (mp, MB_TERM_ADD, t1, t2);                        \
184         t1 = mono_ctree_new (mp, op, t1, sp [2]);                             \
185         ADD_TREE (t1, cli_addr);                                              \
186         break;                                                                \
187 }
188
189 typedef struct {
190         MonoMethod *method;
191         MBTree **arg_map;
192         const unsigned char *end, *saved_ip;
193         MonoImage *saved_image;
194 } MonoInlineInfo;
195         
196 /* Whether to dump the assembly code after genreating it */
197 gboolean mono_jit_dump_asm = FALSE;
198
199 /* Whether to dump the forest */
200 gboolean mono_jit_dump_forest = FALSE;
201
202 /* Whether to print function call traces */
203 gboolean mono_jit_trace_calls = FALSE;
204
205 /* Whether to insert in the code profile callbacks */
206 gboolean mono_jit_profile = FALSE;
207
208 /* Force jit to share code between application domains */
209 gboolean mono_jit_share_code = FALSE;
210
211 /* use linear scan register allocation */
212 gboolean mono_use_linear_scan = TRUE;
213
214 /* inline code */
215 gboolean mono_jit_inline_code = TRUE;
216
217 /* inline memcpy */
218 gboolean mono_inline_memcpy = TRUE;
219
220 /* Use alternative (faster) sequence to convert FP values to integers */
221 gboolean mono_use_fast_iconv = FALSE;
222
223 /* TLS id to store jit data */
224 guint32  mono_jit_tls_id;
225
226 /* issue a breakpoint on unhandled excepions */
227 gboolean mono_break_on_exc = FALSE;
228
229 MonoDebugFormat mono_debug_format = MONO_DEBUG_FORMAT_NONE;
230 GList *mono_debug_methods = NULL;
231
232 /* If non-zero, insert a breakpoint when compiling the next method.
233  * If positive, interpret this variable as a counter and decrement
234  * it after setting the breakpoint. */
235 int mono_debug_insert_breakpoint = 0;
236
237 /* This is the address of the last breakpoint which was inserted. */
238 gchar *mono_debug_last_breakpoint_address = NULL;
239
240 MonoJitStats mono_jit_stats;
241
242 CRITICAL_SECTION *metadata_section = NULL;
243
244 /* 
245  * We sometimes need static data, for example the forest generator need it to
246  * store constants or class data.
247  */
248 inline static gpointer
249 mono_alloc_static (int size)
250 {
251         return g_malloc (size);
252
253 inline static gpointer
254 mono_alloc_static0 (int size)
255 {
256         return g_malloc0 (size);
257
258
259 typedef void (*MonoCCtor) (void);
260
261 static int
262 mono_allocate_intvar (MonoFlowGraph *cfg, int slot, MonoValueType type)
263 {
264         int size, align, vnum, pos;
265         
266         g_assert (type != VAL_UNKNOWN);
267
268         /* take care if you modify MonoValueType */
269         g_assert (VAL_DOUBLE == 4);
270
271         /* fixme: machine dependant */ 
272         if (type == VAL_POINTER)
273                 type = VAL_I32; /* VAL_I32 and VAL_POINTER share the same slot */
274
275         pos = type - 1 + slot * VAL_DOUBLE;
276
277         if ((vnum = cfg->intvars [pos]))                
278                 return vnum;
279         mono_get_val_sizes (type, &size, &align);
280
281         cfg->intvars[pos] = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, type);
282
283         return cfg->intvars[pos];
284 }
285
286 static int
287 mono_allocate_excvar (MonoFlowGraph *cfg)
288 {
289         if (cfg->excvar)
290                 return cfg->excvar;
291
292         cfg->excvar = arch_allocate_var (cfg, 4, 4, MONO_TEMPVAR, VAL_POINTER);
293
294         return cfg->excvar;
295 }
296
297
298 /**
299  * ctree_create_load:
300  * @cfg: pointer to the control flow graph
301  * @type: the type of the value to load
302  * @addr: the address of the value
303  *
304  * Creates a tree to load the value at address @addr.
305  */
306 inline static MBTree *
307 ctree_create_load (MonoFlowGraph *cfg, MonoType *type, MBTree *addr, MonoValueType *svt, gboolean arg)
308 {
309         MonoMemPool *mp = cfg->mp;
310         int ldind;
311         MBTree *t;
312
313         if (arg)
314                 ldind = mono_map_ldarg_type (type, svt);
315         else
316                 ldind = mono_map_ldind_type (type, svt);
317
318         t = mono_ctree_new (mp, ldind, addr, NULL);
319
320         return t;
321 }
322
323 /**
324  * ctree_create_store:
325  * @mp: pointer to a memory pool
326  * @addr_type: address type (MB_TERM_ADDR_L or MB_TERM_ADDR_G)
327  * @s: the value (tree) to store
328  * @type: the type of the value
329  * @addr: the address of the value
330  *
331  * Creates a tree to store the value @s at address @addr.
332  */
333 inline static MBTree *
334 ctree_create_store (MonoFlowGraph *cfg, MonoType *type, MBTree *addr, 
335                     MBTree *s, gboolean arg)
336 {
337         MonoMemPool *mp = cfg->mp;
338         int stind; 
339         MBTree *t;
340         
341         if (arg)
342                 stind = mono_map_starg_type (type);
343         else
344                 stind = mono_map_stind_type (type);
345
346         t = mono_ctree_new (mp, stind, addr, s);
347
348         if (ISSTRUCT (type))
349                 t->data.i = mono_class_value_size (type->data.klass, NULL);
350         
351         return t;
352 }
353
354 inline static MBTree *
355 ctree_dup_address (MonoMemPool *mp, MBTree *s)
356 {
357         MBTree *t;
358
359         switch (s->op) {
360
361         case MB_TERM_ADDR_L:
362         case MB_TERM_ADDR_G:
363                 t = mono_ctree_new_leaf (mp, s->op);
364                 t->data.i = s->data.i;
365                 t->svt = VAL_POINTER;
366                 return t;
367         default:
368                 g_warning ("unknown tree opcode %d", s->op);
369                 g_assert_not_reached ();
370         }
371
372         return NULL;
373 }
374
375 /**
376  * Create a duplicate of the value of a tree. This is
377  * easy for trees starting with LDIND/STIND, since the
378  * duplicate is simple a LDIND tree with the same address.
379  * For other trees we have to split the tree into one tree
380  * storing the value to a new temporary variable, and 
381  * another tree which loads that value back. We can then
382  * duplicate the second tree.
383  */
384 static MBTree *
385 ctree_create_dup (MonoMemPool *mp, MBTree *s)
386 {
387         MBTree *t;
388         
389         switch (s->op) {
390         case MB_TERM_STIND_I1:
391         case MB_TERM_LDIND_I1:
392                 t = ctree_dup_address (mp, s->left);
393                 t = mono_ctree_new (mp, MB_TERM_LDIND_I1, t, NULL);
394                 t->svt = VAL_I32;
395                 break;
396         case MB_TERM_STIND_I2:
397         case MB_TERM_LDIND_I2:
398                 t = ctree_dup_address (mp, s->left);
399                 t = mono_ctree_new (mp, MB_TERM_LDIND_I2, t, NULL);
400                 t->svt = VAL_I32;
401                 break;
402         case MB_TERM_STIND_I4:
403         case MB_TERM_LDIND_I4:
404                 t = ctree_dup_address (mp, s->left);
405                 t = mono_ctree_new (mp, MB_TERM_LDIND_I4, t, NULL);
406                 t->svt = VAL_I32;
407                 break;
408         case MB_TERM_STIND_I8:
409         case MB_TERM_LDIND_I8:
410                 t = ctree_dup_address (mp, s->left);
411                 t = mono_ctree_new (mp, MB_TERM_LDIND_I8, t, NULL);
412                 t->svt = VAL_I64;
413                 break;
414         case MB_TERM_STIND_R4:
415         case MB_TERM_LDIND_R4:
416                 t = ctree_dup_address (mp, s->left);
417                 t = mono_ctree_new (mp, MB_TERM_LDIND_R4, t, NULL);
418                 t->svt = VAL_DOUBLE;
419                 break;
420         case MB_TERM_STIND_R8:
421         case MB_TERM_LDIND_R8:
422                 t = ctree_dup_address (mp, s->left);
423                 t = mono_ctree_new (mp, MB_TERM_LDIND_R8, t, NULL);
424                 t->svt = VAL_DOUBLE;
425                 break;
426         default:
427                 g_warning ("unknown op \"%s\"", mono_burg_term_string [s->op]);
428                 g_assert_not_reached ();
429         }
430
431         return t;
432 }
433
434 static MBTree *
435 mono_store_tree (MonoFlowGraph *cfg, int slot, MBTree *s, MBTree **tdup)
436 {
437         MonoMemPool *mp = cfg->mp;
438         MBTree *t;
439         int vnum = 0;
440
441         switch (s->op) {
442         case MB_TERM_STIND_I1:
443         case MB_TERM_LDIND_I1:
444         case MB_TERM_STIND_I2:
445         case MB_TERM_LDIND_I2:
446         case MB_TERM_STIND_I4:
447         case MB_TERM_LDIND_I4:
448         case MB_TERM_STIND_I8:
449         case MB_TERM_LDIND_I8:
450         case MB_TERM_STIND_R4:
451         case MB_TERM_LDIND_R4:
452         case MB_TERM_STIND_R8:
453         case MB_TERM_LDIND_R8: {
454                 if (slot >= 0) {
455                         vnum = mono_allocate_intvar (cfg, slot, s->svt);
456
457                         if (s->left->op == MB_TERM_ADDR_L && s->left->data.i == vnum) {
458                                 if (tdup)
459                                         *tdup = ctree_create_dup (mp, s);
460                                 return NULL;
461                         }
462                         // fall through
463                 } else {
464                         if (tdup)
465                                 *tdup = ctree_create_dup (mp, s);
466                         return NULL;
467                 }
468         }       
469         default: {
470                         g_assert (s->svt != VAL_UNKNOWN);
471
472                         if (slot >= 0) {
473                                 vnum = mono_allocate_intvar (cfg, slot, s->svt);
474                         } else {
475                                 int size, align;
476                                 mono_get_val_sizes (s->svt, &size, &align);
477                                 vnum = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, s->svt);
478                         }
479
480                         t = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
481                         t->data.i = vnum;
482                        
483                         t = mono_ctree_new (mp, mono_map_store_svt_type (s->svt), t, s);
484                         t->svt = s->svt;
485                 }
486         }
487
488         if (tdup) 
489                 mono_store_tree (cfg, -1, t, tdup);
490
491         return t;
492 }
493
494 static MonoBBlock *
495 mono_find_final_block (MonoFlowGraph *cfg, guint32 ip, guint32 target, int type)
496 {
497         MonoMethod *method = cfg->method;
498         MonoBytecodeInfo *bcinfo = cfg->bcinfo;
499         MonoMethodHeader *header = ((MonoMethodNormal *)method)->header;
500         MonoExceptionClause *clause;
501         int i;
502
503         for (i = 0; i < header->num_clauses; ++i) {
504                 clause = &header->clauses [i];
505
506                 if (MONO_OFFSET_IN_CLAUSE (clause, ip) && 
507                     (!MONO_OFFSET_IN_CLAUSE (clause, target))) {
508                         if (clause->flags & type) {
509                                 g_assert (bcinfo [clause->handler_offset].is_block_start);
510                                 return &cfg->bblocks [bcinfo [clause->handler_offset].block_id];
511                         }
512                 }
513         }
514         return NULL;
515 }
516
517 static void
518 mono_cfg_add_successor (MonoFlowGraph *cfg, MonoBBlock *bb, gint32 target)
519 {
520         MonoBBlock *tbb;
521         GList *l;
522
523         g_assert (cfg->bcinfo [target].is_block_start);
524
525         tbb = &cfg->bblocks [cfg->bcinfo [target].block_id];
526         g_assert (tbb);
527
528         for (l = bb->succ; l; l = l->next) {
529                 MonoBBlock *t = (MonoBBlock *)l->data;
530                 if (t == tbb)
531                         return;
532         }
533
534         bb->succ = g_list_prepend (bb->succ, tbb);
535 }
536
537
538 #define CREATE_BLOCK(t) {if (!bcinfo [t].is_block_start) {block_count++;bcinfo [t].is_block_start = 1; }}
539
540 static void
541 mono_analyze_flow (MonoFlowGraph *cfg)
542 {
543         MonoMethod *method = cfg->method;
544         register const unsigned char *ip, *end;
545         MonoMethodHeader *header;
546         MonoBytecodeInfo *bcinfo;
547         MonoExceptionClause *clause;
548         MonoBBlock *bblocks, *bb;
549         const MonoOpcode *opcode;
550         gboolean block_end;
551         int i, block_count;
552
553         header = ((MonoMethodNormal *)method)->header;
554
555         bcinfo = g_malloc0 (header->code_size * sizeof (MonoBytecodeInfo));
556         bcinfo [0].is_block_start = 1;
557         block_count = 1;
558         block_end = FALSE;
559
560         ip = header->code;
561         end = ip + header->code_size;
562
563         mono_jit_stats.cil_code_size += header->code_size;
564
565         /* fixme: add block boundaries for exceptions */
566         for (i = 0; i < header->num_clauses; ++i) {
567                 clause = &header->clauses [i];
568                 CREATE_BLOCK (clause->try_offset);
569                 CREATE_BLOCK (clause->handler_offset);
570         }
571
572         while (ip < end) {
573                 guint32 cli_addr = ip - header->code;
574
575                 //printf ("IL%04x OPCODE %s\n", cli_addr, mono_opcode_names [*ip]);
576                 
577                 if (block_end) {
578                         CREATE_BLOCK (cli_addr);
579                         block_end = FALSE;
580                 }
581
582                 if (*ip == 0xfe) {
583                         ++ip;
584                         i = *ip + 256;
585                 } else {
586                         i = *ip;
587                 }
588
589                 opcode = &mono_opcodes [i];
590
591                 switch (opcode->flow_type) {
592                 case MONO_FLOW_RETURN:
593                 case MONO_FLOW_ERROR:
594                         block_end = 1;
595                         break;
596                 case MONO_FLOW_BRANCH: /* we handle branch when checking the argument type */
597                 case MONO_FLOW_COND_BRANCH:
598                 case MONO_FLOW_CALL:
599                 case MONO_FLOW_NEXT:
600                 case MONO_FLOW_META:
601                         break;
602                 default:
603                         g_assert_not_reached ();
604                 }
605
606                 switch (opcode->argument) {
607                 case MonoInlineNone:
608                         ++ip;
609                         break;
610                 case MonoInlineString:
611                         mono_ldstr (mono_domain_get (), method->klass->image, mono_metadata_token_index (read32 (ip + 1)));
612                         /* fall through */
613                 case MonoInlineType:
614                 case MonoInlineField:
615                 case MonoInlineMethod:
616                 case MonoInlineTok:
617                 case MonoInlineSig:
618                 case MonoShortInlineR:
619                 case MonoInlineI:
620                         ip += 5;
621                         break;
622                 case MonoInlineVar:
623                         ip += 3;
624                         break;
625                 case MonoShortInlineVar:
626                 case MonoShortInlineI:
627                         ip += 2;
628                         break;
629                 case MonoShortInlineBrTarget:
630                         ip++;
631                         i = (signed char)*ip;
632                         ip++;
633                         CREATE_BLOCK (cli_addr + 2 + i);
634                         block_end = 1;
635                        
636                         break;
637                 case MonoInlineBrTarget:
638                         ip++;
639                         i = read32 (ip);
640                         ip += 4;
641                         CREATE_BLOCK (cli_addr + 5 + i);
642                         block_end = 1;
643                         break;
644                 case MonoInlineSwitch: {
645                         gint32 st, target, n;
646                         ++ip;
647                         n = read32 (ip);
648                         ip += 4;
649                         st = cli_addr + 5 + 4 * n;
650                         CREATE_BLOCK (st);
651
652                         for (i = 0; i < n; i++) {
653                                 target = read32 (ip) + st;
654                                 ip += 4;
655                                 CREATE_BLOCK (target);                  
656                         }
657                         /*
658                          * Note: the code didn't set block_end in switch.
659                          */
660                         break;
661                 }
662                 case MonoInlineR:
663                 case MonoInlineI8:
664                         ip += 9;
665                         break;
666                 default:
667                         g_assert_not_reached ();
668                 }
669         }
670
671
672         g_assert (block_count);
673
674         bb = bblocks  = g_malloc0 (sizeof (MonoBBlock) * block_count);
675
676         block_count = 0;
677         bblocks [0].reached = 1;
678
679         for (i = 0; i < header->code_size; i++) {
680                 if (bcinfo [i].is_block_start) {
681                         bb->cli_addr = i;
682                         bb->num = block_count;
683                         bb->forest = g_ptr_array_new ();
684                         if (block_count)
685                                 bb [-1].length = i - bb [-1].cli_addr; 
686                         bcinfo [i].block_id = block_count;
687                         bb++;
688                         block_count++;
689                 }
690         }
691         bb [-1].length = header->code_size - bb [-1].cli_addr; 
692
693         cfg->bcinfo = bcinfo;
694         cfg->bblocks = bblocks;
695         cfg->block_count = block_count;
696
697         mono_jit_stats.basic_blocks += block_count;
698         mono_jit_stats.max_basic_blocks = MAX (block_count, mono_jit_stats.max_basic_blocks);
699        
700         for (i = 0; i < header->num_clauses; ++i) {
701                 MonoBBlock *sbb, *tbb;
702                 clause = &header->clauses [i];
703                 sbb = &cfg->bblocks [bcinfo [clause->try_offset].block_id];
704                 tbb = &cfg->bblocks [bcinfo [clause->handler_offset].block_id];
705                 g_assert (sbb && tbb);
706                 sbb->succ = g_list_prepend (sbb->succ, tbb);
707         }
708
709         ip = header->code;
710         end = ip + header->code_size;
711         bb = NULL;
712
713         while (ip < end) {
714                 guint32 cli_addr = ip - header->code;
715
716                 if (bcinfo [cli_addr].is_block_start) {
717                         MonoBBlock *tbb = &cfg->bblocks [bcinfo [cli_addr].block_id];           
718                         if (bb && !bb->succ)
719                                 bb->succ = g_list_prepend (bb->succ, tbb);
720                         bb = tbb;
721                 }
722                 g_assert (bb);
723
724                 if (*ip == 0xfe) {
725                         ++ip;
726                         i = *ip + 256;
727                 } else {
728                         i = *ip;
729                 }
730
731                 opcode = &mono_opcodes [i];
732
733                 switch (opcode->argument) {
734                 case MonoInlineNone:
735                         ++ip;
736                         break;
737                 case MonoInlineString:
738                 case MonoInlineType:
739                 case MonoInlineField:
740                 case MonoInlineMethod:
741                 case MonoInlineTok:
742                 case MonoInlineSig:
743                 case MonoShortInlineR:
744                 case MonoInlineI:
745                         ip += 5;
746                         break;
747                 case MonoInlineVar:
748                         ip += 3;
749                         break;
750                 case MonoShortInlineVar:
751                 case MonoShortInlineI:
752                         ip += 2;
753                         break;
754                 case MonoShortInlineBrTarget:
755                         ip++;
756                         i = (signed char)*ip;
757                         ip++;
758                         mono_cfg_add_successor (cfg, bb, cli_addr + 2 + i);
759                         if (opcode->flow_type == MONO_FLOW_COND_BRANCH)
760                                 mono_cfg_add_successor (cfg, bb, cli_addr + 2);
761                         break;
762                 case MonoInlineBrTarget:
763                         ip++;
764                         i = read32 (ip);
765                         ip += 4;
766                         mono_cfg_add_successor (cfg, bb, cli_addr + 5 + i);
767                         if (opcode->flow_type == MONO_FLOW_COND_BRANCH)
768                                 mono_cfg_add_successor (cfg, bb, cli_addr + 5);
769                         break;
770                 case MonoInlineSwitch: {
771                         gint32 st, target, n;
772                         ++ip;
773                         n = read32 (ip);
774                         ip += 4;
775                         st = cli_addr + 5 + 4 * n;
776                         mono_cfg_add_successor (cfg, bb, st);
777
778                         for (i = 0; i < n; i++) {
779                                 target = read32 (ip) + st;
780                                 ip += 4;
781                                 mono_cfg_add_successor (cfg, bb, target);
782                         }
783                         break;
784                 }
785                 case MonoInlineR:
786                 case MonoInlineI8:
787                         ip += 9;
788                         break;
789                 default:
790                         g_assert_not_reached ();
791                 }
792         }
793 }
794
795 /**
796  * ves_array_element_address:
797  * @this: a pointer to the array object
798  *
799  * Returns: the address of an array element.
800  */
801 static gpointer 
802 ves_array_element_address (MonoArray *this, ...)
803 {
804         MonoClass *class;
805         va_list ap;
806         int i, ind, esize;
807         gpointer ea;
808
809         g_assert (this != NULL);
810
811         va_start(ap, this);
812
813         class = this->obj.vtable->klass;
814
815         ind = va_arg(ap, int);
816         if (this->bounds != NULL) {
817                 ind -= this->bounds [0].lower_bound;
818                 for (i = 1; i < class->rank; i++) {
819                         ind = ind*this->bounds [i].length + va_arg(ap, int) -
820                                 this->bounds [i].lower_bound;;
821                 }
822         }
823
824         esize = mono_array_element_size (class);
825         ea = (gpointer*)((char*)this->vector + (ind * esize));
826         //printf ("AADDRESS %p %p %d\n", this, ea, ind);
827
828         va_end(ap);
829
830         return ea;
831 }
832
833 static MonoArray *
834 mono_array_new_va (MonoMethod *cm, ...)
835 {
836         MonoDomain *domain = mono_domain_get ();
837         va_list ap;
838         guint32 *lengths;
839         guint32 *lower_bounds;
840         int pcount = cm->signature->param_count;
841         int rank = cm->klass->rank;
842         int i, d;
843
844         va_start (ap, cm);
845
846         lengths = alloca (sizeof (guint32) * pcount);
847         for (i = 0; i < pcount; ++i)
848                 lengths [i] = d = va_arg(ap, int);
849
850         if (rank == pcount) {
851                 /* Only lengths provided. */
852                 lower_bounds = NULL;
853         } else {
854                 g_assert (pcount == (rank * 2));
855                 /* lower bounds are first. */
856                 lower_bounds = lengths;
857                 lengths += rank;
858         }
859         va_end(ap);
860
861         return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
862 }
863
864 #define ADD_TREE(t,a)   do { t->cli_addr = a; g_ptr_array_add (forest, (t)); } while (0)
865 #define PUSH_TREE(t,k)  do { int tt = k; *sp = t; t->svt = tt; sp++; } while (0)
866
867 #define LOCAL_POS(n)    (1 + n)
868
869 #ifdef OPT_BOOL
870 #define LOCAL_TYPE(n)   ((header)->locals [(n)]->type == MONO_TYPE_BOOLEAN && !(header)->locals [(n)]->byref ? &mono_defaults.int32_class->byval_arg : (header)->locals [(n)])
871 #else
872 #define LOCAL_TYPE(n)   ((header)->locals [(n)])
873 #endif
874
875 #define ARG_POS(n)      (firstarg + n)
876 #define ARG_TYPE(n)     ((n) ? (signature)->params [(n) - (signature)->hasthis] : \
877                         (signature)->hasthis ? &method->klass->this_arg: (signature)->params [(0)])
878
879
880 /*
881  * replaces all occurences of variable @varnum in @tree with @copy. 
882  */
883 static void
884 mono_copy_used_var (MonoFlowGraph *cfg, MBTree *tree, int varnum, MBTree **copy)
885 {
886         MBTree *t1, *t2;
887         int v, size, align;
888
889         if (tree->left)
890                 mono_copy_used_var (cfg, tree->left, varnum, copy);
891         if (tree->right)
892                 mono_copy_used_var (cfg, tree->right, varnum, copy);
893
894         switch (tree->op) {
895         case MB_TERM_LDIND_I1:
896         case MB_TERM_LDIND_I2:
897         case MB_TERM_LDIND_I4:
898         case MB_TERM_LDIND_I8:
899         case MB_TERM_LDIND_R4:
900         case MB_TERM_LDIND_R8:
901                 if (tree->left->op == MB_TERM_ADDR_L &&
902                     tree->left->data.i == varnum) {
903                         if (*copy) {
904                                 tree->left->data.i = (*copy)->left->data.i;
905                                 return;
906                         } 
907                         
908                         mono_get_val_sizes (tree->svt, &size, &align);
909                         v = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, tree->svt);
910  
911                         t1 = mono_ctree_new_leaf (cfg->mp, MB_TERM_ADDR_L);
912                         t1->data.i = v;
913                        
914                         t2 = mono_ctree_new_leaf (cfg->mp, MB_TERM_ADDR_L);
915                         t2->data.i = varnum;
916                         t2 = mono_ctree_new (cfg->mp, tree->op, t2, NULL);
917
918                         t2 = mono_ctree_new (cfg->mp, mono_map_store_svt_type (tree->svt), t1, t2);
919                         t2->svt = tree->svt;
920
921                         tree->left->data.i = v;
922
923                         *copy = t2;
924                 }
925         }
926 }
927
928 /* 
929  * if a variable is modified and there are still referencence
930  * to it on the runtime stack we need to store the value into
931  * a temporary variable and use that value instead of the 
932  * modified one.
933  */
934 static MBTree *
935 mono_stack_duplicate_used_var (MonoFlowGraph *cfg, MBTree **stack, MBTree **sp, int varnum)
936 {
937         MBTree *res = NULL;
938
939         while (stack < sp) {
940                 mono_copy_used_var (cfg, *stack, varnum, &res);
941                 stack++;
942         }
943
944         return res;
945 }
946
947 static int
948 check_inlining (MonoMethod *method)
949 {
950         MonoMethodHeader *header;
951         MonoMethodSignature *signature = method->signature;
952         register const unsigned char *ip, *end;
953         gboolean stop;
954         int i, arg_used [256];
955
956         g_assert (method);
957
958         if (method->inline_info)
959                 return method->inline_count;
960
961         method->inline_info = 1;
962         
963         if ((method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
964             (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
965             (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
966             (method->klass->marshalbyref) ||
967             ISSTRUCT (signature->ret))
968                 goto fail;;
969        
970         if (!(header = ((MonoMethodNormal *)method)->header) ||
971             header->num_clauses)
972                 goto fail;;
973
974         if (header->num_clauses)
975                 goto fail;
976         
977         ip = header->code;
978         end = ip + header->code_size;
979
980         for (i = 0; i < 256; i++)
981                 arg_used [i] = 0;
982
983         stop = FALSE;        
984         while (!stop && ip < end) {
985
986                 switch (*ip) {
987                 case CEE_NOP:
988                 case CEE_BREAK:
989                 case CEE_DUP:
990                 case CEE_POP:
991                 case CEE_LDIND_I1:
992                 case CEE_LDIND_U1:
993                 case CEE_LDIND_I2:
994                 case CEE_LDIND_U2:
995                 case CEE_LDIND_I4:
996                 case CEE_LDIND_U4:
997                 case CEE_LDIND_I8:
998                 case CEE_LDIND_I:
999                 case CEE_LDIND_R4:
1000                 case CEE_LDIND_R8:
1001                 case CEE_LDIND_REF:
1002                 case CEE_STIND_REF:
1003                 case CEE_STIND_I1:
1004                 case CEE_STIND_I2:
1005                 case CEE_STIND_I4:
1006                 case CEE_STIND_I8:
1007                 case CEE_STIND_R4:
1008                 case CEE_STIND_R8:
1009                 case CEE_ADD:
1010                 case CEE_SUB:
1011                 case CEE_MUL:
1012                 case CEE_DIV:
1013                 case CEE_DIV_UN:
1014                 case CEE_REM:
1015                 case CEE_REM_UN:
1016                 case CEE_AND:
1017                 case CEE_OR:
1018                 case CEE_XOR:
1019                 case CEE_SHL:
1020                 case CEE_SHR:
1021                 case CEE_SHR_UN:
1022                 case CEE_NEG:
1023                 case CEE_NOT:
1024                 case CEE_CONV_I1:
1025                 case CEE_CONV_I2:
1026                 case CEE_CONV_I4:
1027                 case CEE_CONV_I8:
1028                 case CEE_CONV_R4:
1029                 case CEE_CONV_R8:
1030                 case CEE_CONV_U4:
1031                 case CEE_CONV_U8:
1032                 case CEE_CONV_R_UN:
1033                 case CEE_CONV_OVF_I1_UN:
1034                 case CEE_CONV_OVF_I2_UN:
1035                 case CEE_CONV_OVF_I4_UN:
1036                 case CEE_CONV_OVF_I8_UN:
1037                 case CEE_CONV_OVF_U1_UN:
1038                 case CEE_CONV_OVF_U2_UN:
1039                 case CEE_CONV_OVF_U4_UN:
1040                 case CEE_CONV_OVF_U8_UN:
1041                 case CEE_CONV_OVF_I_UN:
1042                 case CEE_CONV_OVF_U_UN:
1043                 case CEE_LDLEN:
1044                 case CEE_LDELEM_I1:
1045                 case CEE_LDELEM_U1:
1046                 case CEE_LDELEM_I2:
1047                 case CEE_LDELEM_U2:
1048                 case CEE_LDELEM_I4:
1049                 case CEE_LDELEM_U4:
1050                 case CEE_LDELEM_I8:
1051                 case CEE_LDELEM_I:
1052                 case CEE_LDELEM_R4:
1053                 case CEE_LDELEM_R8:
1054                 case CEE_LDELEM_REF:
1055                 case CEE_STELEM_I:
1056                 case CEE_STELEM_I1:
1057                 case CEE_STELEM_I2:
1058                 case CEE_STELEM_I4:
1059                 case CEE_STELEM_I8:
1060                 case CEE_STELEM_R4:
1061                 case CEE_STELEM_R8:
1062                 case CEE_STELEM_REF:
1063                 case CEE_CONV_OVF_I1:
1064                 case CEE_CONV_OVF_U1:
1065                 case CEE_CONV_OVF_I2:
1066                 case CEE_CONV_OVF_U2:
1067                 case CEE_CONV_OVF_I4:
1068                 case CEE_CONV_OVF_U4:
1069                 case CEE_CONV_OVF_I8:
1070                 case CEE_CONV_OVF_U8:
1071                 case CEE_CKFINITE:
1072                 case CEE_CONV_U2:
1073                 case CEE_CONV_U1:
1074                 case CEE_CONV_I:
1075                 case CEE_CONV_OVF_I:
1076                 case CEE_CONV_OVF_U:
1077                 case CEE_ADD_OVF:
1078                 case CEE_ADD_OVF_UN:
1079                 case CEE_MUL_OVF:
1080                 case CEE_MUL_OVF_UN:
1081                 case CEE_SUB_OVF:
1082                 case CEE_SUB_OVF_UN:
1083                 case CEE_STIND_I:
1084                 case CEE_CONV_U:
1085                 case CEE_LDNULL:
1086                 case CEE_LDC_I4_M1:
1087                 case CEE_LDC_I4_0:
1088                 case CEE_LDC_I4_1:
1089                 case CEE_LDC_I4_2:
1090                 case CEE_LDC_I4_3:
1091                 case CEE_LDC_I4_4:
1092                 case CEE_LDC_I4_5:
1093                 case CEE_LDC_I4_6:
1094                 case CEE_LDC_I4_7:
1095                 case CEE_LDC_I4_8:
1096                         ++ip;
1097                         break;
1098                 case CEE_LDC_I4_S:
1099                         ip += 2;
1100                         break;
1101                 case CEE_LDC_I4:
1102                 case CEE_LDC_R4:
1103                 case CEE_CPOBJ:
1104                 case CEE_LDOBJ:
1105                 case CEE_LDSTR:
1106                 case CEE_NEWOBJ:
1107                 case CEE_CASTCLASS:
1108                 case CEE_ISINST:
1109                 case CEE_UNBOX:
1110                 case CEE_LDFLD:
1111                 case CEE_LDFLDA:
1112                 case CEE_STFLD:
1113                 case CEE_LDSFLD:
1114                 case CEE_LDSFLDA:
1115                 case CEE_STSFLD:
1116                 case CEE_STOBJ:
1117                 case CEE_BOX:
1118                 case CEE_NEWARR:
1119                 case CEE_LDELEMA:
1120                 case CEE_LDTOKEN:
1121                         ip += 5;
1122                         break;
1123                 case CEE_LDC_I8:
1124                 case CEE_LDC_R8:
1125                         ip += 9;
1126                         break;
1127                 case CEE_CALL:
1128                 case CEE_CALLVIRT: {
1129                         MonoMethod *cm;
1130                         guint32 token;
1131                         ++ip;
1132                         token = read32 (ip);
1133                         ip += 4;
1134
1135                         cm = mono_get_method (method->klass->image, token, NULL);
1136                         g_assert (cm);
1137
1138                         if (cm == method)
1139                                 goto fail;
1140
1141                         break;
1142                 }
1143                 case CEE_LDARG_0:
1144                 case CEE_LDARG_1:
1145                 case CEE_LDARG_2:
1146                 case CEE_LDARG_3: {
1147                         int an = (*ip) - CEE_LDARG_0;
1148                         if (arg_used [an])
1149                                 goto fail;
1150                         arg_used [an] = TRUE;
1151                         ++ip;
1152                         break;
1153                 }       
1154                 case CEE_LDARG_S:
1155                         ++ip;
1156                         if (arg_used [*ip])
1157                                 goto fail;
1158                         arg_used [*ip] = TRUE;
1159                         ++ip;
1160                         break;
1161         
1162                 case CEE_PREFIX1: {
1163                         ++ip;                   
1164                         switch (*ip) {
1165                         case CEE_LDARG: {
1166                                 guint16 an;
1167                                 ip++;
1168                                 an = read16 (ip);
1169                                 ip += 2;
1170                                 if (an > 255 || arg_used [an])
1171                                         goto fail;
1172                                 arg_used [an] = TRUE;
1173                                 break;
1174                         }       
1175
1176                         case CEE_CEQ:
1177                         case CEE_CGT:
1178                         case CEE_CGT_UN:
1179                         case CEE_CLT:
1180                         case CEE_CLT_UN:
1181                         case CEE_CPBLK:
1182                         case CEE_INITBLK:
1183                                 ip++;
1184                                 break;
1185                         case CEE_LDFTN:
1186                         case CEE_LDVIRTFTN: {
1187                                 MonoMethod *cm;
1188                                 guint32 token;
1189                                 ++ip;
1190                                 token = read32 (ip);
1191                                 ip += 4;
1192
1193                                 cm = mono_get_method (method->klass->image, token, NULL);
1194                                 g_assert (cm);
1195
1196                                 if (cm == method)
1197                                         goto fail;
1198                                 
1199                                 break;
1200                         }
1201                         case CEE_INITOBJ:
1202                         case CEE_SIZEOF:
1203                                 ip += 5;
1204                                 break;
1205                         default:
1206                                 stop = TRUE;
1207                                 break;
1208                         }
1209                 }
1210                 default:
1211                         stop = TRUE;
1212                         break;                  
1213                 }
1214         }
1215
1216         if (ip < end &&
1217             !(ip [0] == CEE_RET ||
1218               ((ip + 4) < end &&
1219                ip [0] == CEE_STLOC_0 &&
1220                ip [1] == CEE_BR_S &&
1221                ip [2] == 0 &&
1222                ip [3] == CEE_LDLOC_0 &&
1223                ip [4] == CEE_RET)))
1224                 goto fail;
1225         
1226         if (signature->hasthis && arg_used [0])
1227                 method->uses_this = 1;
1228
1229         mono_jit_stats.inlineable_methods++;
1230
1231         return method->inline_count = ip - header->code;
1232
1233  fail:
1234         return method->inline_count = -1;
1235 }
1236
1237 static void
1238 create_outstack (MonoFlowGraph *cfg, MonoBBlock *bb, MBTree **stack, int depth)
1239 {
1240         MonoMemPool *mp = cfg->mp;
1241         MBTree **c = stack, *t1, *t2;
1242         GPtrArray *forest = bb->forest;
1243         int i;
1244
1245         g_assert (bb->reached);
1246
1247         if (depth <= 0)
1248                 return;
1249
1250         if (bb->outstack) {
1251                 g_assert (bb->outdepth == depth);
1252                 return;
1253         }
1254
1255         bb->outdepth = depth;
1256         bb->outstack = mono_mempool_alloc (mp, depth * sizeof (MBTree *));
1257         
1258         for (i = 0; i < depth; i++) {
1259                 if ((t1 = mono_store_tree (cfg, i, c [i], &t2)))
1260                         ADD_TREE (t1, -1);
1261                 bb->outstack [i] = t2;
1262         }
1263 }
1264
1265 static void
1266 mark_reached (MonoFlowGraph *cfg, MonoBBlock *target, MBTree **stack, int depth)
1267 {
1268         MonoMemPool *mp = cfg->mp;
1269         int i;
1270
1271         if (target->reached)
1272                 return;
1273
1274         target->reached = 1;
1275
1276         if (depth == 0)
1277                 return;
1278
1279         g_assert (stack);
1280
1281         if (target->instack) {
1282                 g_assert (target->indepth == depth);
1283                 return;
1284         }
1285
1286         target->indepth = depth;
1287         target->instack = mono_mempool_alloc (mp, depth * sizeof (MBTree *));
1288         
1289         for (i = 0; i < depth; i++) {
1290                 target->instack [i] = ctree_create_dup (mp, stack [i]);
1291         }
1292         
1293         
1294 }
1295
1296 #define MARK_REACHED(bb) do { if (!bb->reached) { bb->reached = 1; }} while (0)
1297
1298 /**
1299  * mono_analyze_stack:
1300  * @cfg: control flow graph
1301  *
1302  * This is the architecture independent part of JIT compilation.
1303  * It creates a forest of trees which can then be fed into the
1304  * architecture dependent code generation.
1305  *
1306  * The algorithm is from Andi Krall, the same is used in CACAO
1307  */
1308 static gboolean
1309 mono_analyze_stack (MonoFlowGraph *cfg)
1310 {
1311         MonoMethod *method = cfg->method;
1312         MonoMemPool *mp = cfg->mp;
1313         MonoBytecodeInfo *bcinfo = cfg->bcinfo;
1314         MonoMethodHeader *header;
1315         MonoMethodSignature *signature;
1316         MonoImage *image;
1317         MonoValueType svt;
1318         MBTree **sp, **stack, **arg_sp, **arg_map = NULL, *t1, *t2, *t3;
1319         register const unsigned char *ip, *end;
1320         GPtrArray *forest;
1321         int i, j, depth, repeat_count;
1322         int varnum = 0, firstarg = 0, retvtarg = 0;
1323         gboolean repeat, superblock_end;
1324         MonoBBlock *bb, *tbb;
1325         int maxstack;
1326         GList *inline_list = NULL;
1327
1328         header = ((MonoMethodNormal *)method)->header;
1329         signature = method->signature;
1330         image = method->klass->image; 
1331
1332         /* we add 10 extra slots for method inlining */
1333         maxstack = header->max_stack + 10;
1334         sp = stack = alloca (sizeof (MBTree *) * (maxstack + 1));
1335
1336         if (header->num_locals) {
1337                 int size, align;
1338                 
1339                 for (i = 0; i < header->num_locals; ++i) {
1340                         MonoValueType svt;
1341                         size = mono_type_size (LOCAL_TYPE (i), &align);
1342                         mono_map_ldind_type (header->locals [i], &svt);
1343                         varnum = arch_allocate_var (cfg, size, align, MONO_LOCALVAR, svt);
1344                         if (i == 0)
1345                                 cfg->locals_start_index = varnum;
1346                 }
1347         }
1348
1349         if (ISSTRUCT (signature->ret)) {
1350                 int size, align;
1351
1352                 cfg->has_vtarg = 1;
1353
1354                 size = mono_type_size (signature->ret, &align);
1355                 
1356                 retvtarg = varnum = arch_allocate_var (cfg, size, align, MONO_LOCALVAR, VAL_UNKNOWN);
1357                 
1358                 //printf ("VALUETYPE METHOD %s.%s::%s %d\n", method->klass->name_space, 
1359                 //method->klass->name, method->name, size);
1360         }
1361         
1362         cfg->args_start_index = firstarg = varnum + 1;
1363  
1364         if (signature->hasthis) {
1365                 int thisvar;
1366                 thisvar = arch_allocate_var (cfg, sizeof (gpointer), sizeof (gpointer), MONO_ARGVAR, VAL_POINTER);
1367                 VARINFO (cfg, thisvar).isvolatile = 1;
1368         }
1369
1370         if (signature->param_count) {
1371                 int align, size;
1372
1373                 for (i = 0; i < signature->param_count; ++i) {
1374                         int argvar;
1375                         size = mono_type_stack_size (signature->params [i], &align);
1376                         argvar = arch_allocate_var (cfg, size, align, MONO_ARGVAR, VAL_UNKNOWN);
1377                         VARINFO (cfg, argvar).isvolatile = 1;
1378                 }
1379         }
1380
1381         for (i = 0; i < header->num_clauses; ++i) {
1382                 MonoExceptionClause *clause = &header->clauses [i];             
1383                 tbb = &cfg->bblocks [bcinfo [clause->handler_offset].block_id];
1384                 if (clause->flags == MONO_EXCEPTION_CLAUSE_NONE) {
1385                         tbb->instack = mono_mempool_alloc (mp, sizeof (MBTree *));
1386                         tbb->indepth = 1;
1387                         tbb->instack [0] = t1 = mono_ctree_new_leaf (mp, MB_TERM_EXCEPTION);
1388                         t1->data.i = mono_allocate_excvar (cfg);
1389                         t1->svt = VAL_POINTER;
1390                         tbb->reached = 1;
1391                 } else if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
1392                         mark_reached (cfg, tbb, NULL, 0);
1393                 } else {
1394                         g_warning ("implement me");
1395                         g_assert_not_reached ();
1396                 }
1397         }
1398
1399         repeat_count = 0;
1400
1401         do {
1402                 repeat = FALSE;
1403                 superblock_end = TRUE;
1404                 sp = stack;
1405
1406                 //printf ("START\n");
1407                 for (i = 0; i < cfg->block_count; i++) {
1408                         bb = &cfg->bblocks [i];
1409                         
1410                         //printf ("BBS %d %05x %05x %d %d %d %s\n", i, bb->cli_addr, bb->cli_addr + bb->length, bb->reached, bb->finished, superblock_end, method->name);
1411                         
1412                         if (!bb->reached && !superblock_end) {
1413                                 MonoBBlock *sbb = &cfg->bblocks [i - 1];
1414
1415                                 g_assert (sbb->outdepth == (sp - stack));
1416
1417                                 mark_reached (cfg, bb, sbb->outstack, sbb->outdepth);
1418                         } 
1419                         
1420                         if (bb->reached) {
1421
1422                                 if (!bb->finished) {
1423
1424                                         sp = stack;
1425
1426                                         for (j = 0; j < bb->indepth; j++) {
1427                                                 sp [j] = bb->instack [j];
1428                                         }
1429                                         sp += bb->indepth;
1430
1431                                         bb->finished = 1;
1432                                 
1433                                         ip = header->code + bb->cli_addr;
1434                                         end = ip + bb->length;
1435
1436                                         forest = bb->forest;
1437                                 
1438                                         superblock_end = FALSE;
1439
1440
1441         while (inline_list || ip < end) {
1442                 guint32 cli_addr;
1443
1444                 if (inline_list) {
1445                         MonoInlineInfo *ii = (MonoInlineInfo *)inline_list->data;
1446                         if (ip >= ii->end) {
1447                                 inline_list = g_list_remove_link (inline_list, inline_list);
1448                                 ip = ii->saved_ip;
1449                                 image = ii->saved_image;
1450                                 if (inline_list)
1451                                         arg_map = ((MonoInlineInfo *)inline_list->data)->arg_map;
1452                                 else 
1453                                         arg_map = NULL;
1454                                 continue;
1455                         }
1456                 } else 
1457                         cli_addr = ip - header->code;
1458
1459                 
1460                 //if (inline_list) printf ("INLINE IL%04x OPCODE %s\n", cli_addr, mono_opcode_names [*ip]);
1461
1462                 //printf ("%d IL%04x OPCODE %s %d %d %d\n", i, cli_addr, mono_opcode_names [*ip], 
1463                 //forest->len, superblock_end, sp - stack);
1464
1465                 switch (*ip) {
1466                         case CEE_THROW: {
1467                         --sp;
1468                         ip++;
1469                         
1470                         t1 = mono_ctree_new (mp, MB_TERM_THROW, *sp, NULL);
1471                         ADD_TREE (t1, cli_addr);                
1472                         superblock_end = TRUE;
1473                         break;
1474                 }
1475                 case CEE_BOX: {
1476                         MonoClass *c;
1477                         guint32 token;
1478                         
1479                         --sp;
1480                         ++ip;
1481                         token = read32 (ip);
1482                         ip += 4;
1483                         
1484                         c = mono_class_get (image, token);
1485                         
1486                         t1 = mono_ctree_new_leaf (mp, MB_TERM_NEWOBJ);
1487                         t1->data.p = c;
1488                         t1->svt = VAL_POINTER;
1489
1490                         t1 = mono_store_tree (cfg, -1, t1, &t3);
1491                         g_assert (t1);
1492                         ADD_TREE (t1, cli_addr);
1493
1494                         t1 = ctree_create_dup (mp, t3);
1495                         t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1496                         t2->data.i = sizeof (MonoObject);
1497                         t1 = mono_ctree_new (mp, MB_TERM_ADD, t1, t2);
1498
1499                         t1 = ctree_create_store (cfg, &c->byval_arg, t1, *sp, FALSE);
1500                         ADD_TREE (t1, cli_addr);
1501
1502                         PUSH_TREE (t3, VAL_POINTER);
1503
1504                         break;
1505                 }
1506                 case CEE_UNBOX: {
1507                         MonoClass *class;
1508                         guint32 token;
1509
1510                         ++ip;
1511                         token = read32 (ip);
1512                         ip += 4;
1513                         sp--;
1514
1515                         class = mono_class_get (image, token);
1516                         t1 = mono_ctree_new (mp, MB_TERM_UNBOX, *sp, NULL);
1517                         t1->data.klass = class;
1518
1519                         PUSH_TREE (t1, VAL_POINTER);
1520                         break;
1521                 }
1522                 case CEE_LDLEN: {
1523                         ip++;
1524                         sp--;
1525
1526                         t1 = mono_ctree_new (mp, MB_TERM_LDLEN, *sp, NULL);
1527                         PUSH_TREE (t1, VAL_I32);
1528                         break;
1529                 }
1530
1531                 case CEE_LDOBJ: {
1532                         guint32 token;
1533                         MonoClass *c;
1534
1535                         ++ip;
1536                         token = read32 (ip);
1537                         ip += 4;
1538                         sp--;
1539
1540                         c = mono_class_get (image, token);
1541                         g_assert (c->valuetype);
1542
1543                         t1 = ctree_create_load (cfg, &c->byval_arg, *sp, &svt, FALSE);
1544                         PUSH_TREE (t1, svt);
1545                         break;
1546                 }
1547                 case CEE_STOBJ: {
1548                         guint32 token;
1549                         MonoClass *c;
1550                         int size;
1551
1552                         ++ip;
1553                         token = read32 (ip);
1554                         ip += 4;
1555                         sp -= 2;
1556
1557                         c = mono_class_get (image, token);
1558                         g_assert (c->valuetype);
1559
1560                         size = mono_class_value_size (c, NULL);
1561                         
1562                         t1 = mono_ctree_new (mp, MB_TERM_STIND_OBJ, sp [0], sp [1]);
1563                         t1->data.i = size;
1564                         ADD_TREE (t1, cli_addr);
1565                         break;
1566                 }
1567                 case CEE_LDSTR: {
1568                         MonoObject *o;
1569                         guint32 ind;
1570
1571                         ++ip;
1572                         ind = mono_metadata_token_index (read32 (ip));
1573                         ip += 4;
1574
1575                         if (cfg->share_code) {
1576                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_LDSTR);
1577                                 t1->data.i = ind;
1578                         } else {
1579                                 o = (MonoObject *) mono_ldstr (cfg->domain, image, ind);
1580                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1581                                 t1->data.p = o;
1582                         }
1583
1584                         PUSH_TREE (t1, VAL_POINTER);
1585                         break;
1586                 }
1587                 case CEE_LDSFLD:
1588                 case CEE_LDSFLDA: {
1589                         MonoClass *klass;
1590                         MonoClassField *field;
1591                         guint32 token;
1592                         int load_addr = *ip == CEE_LDSFLDA;
1593
1594                         ++ip;
1595                         token = read32 (ip);
1596                         ip += 4;
1597                         
1598                         /* need to handle fieldrefs */
1599                         if (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF) {
1600                                 field = mono_field_from_memberref (image, token, &klass);
1601                                 mono_class_init (klass);
1602                         } else {
1603                                 klass = mono_class_get (image, 
1604                                         MONO_TOKEN_TYPE_DEF | mono_metadata_typedef_from_field (image, token & 0xffffff));
1605                                 mono_class_init (klass);
1606                                 field = mono_class_get_field (klass, token);
1607                         }
1608
1609                         g_assert (field);
1610
1611                         if (cfg->share_code) {
1612                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1613                                 t1->data.i = field->offset;
1614                                 t1 = mono_ctree_new (mp, MB_TERM_LDSFLDA, t1, NULL);
1615                                 t1->data.klass = klass;
1616                         } else {
1617                                 MonoVTable *vt = mono_class_vtable (cfg->domain, klass);
1618                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
1619                                 t1->data.p = (char*)(vt->data) + field->offset;
1620                         }
1621                         
1622                         if (load_addr) {
1623                                 svt = VAL_POINTER;
1624                         } else {
1625                                 t1 = ctree_create_load (cfg, field->type, t1, &svt, FALSE);
1626                         }
1627
1628                         PUSH_TREE (t1, svt);
1629                         break;
1630                 }
1631                 case CEE_LDFLD:
1632                 case CEE_LDFLDA: {
1633                         MonoClass *klass;
1634                         MonoClassField *field;
1635                         guint32 token;
1636                         int load_addr = *ip == CEE_LDFLDA;
1637
1638                         ++ip;
1639                         token = read32 (ip);
1640                         ip += 4;
1641                         sp--;
1642
1643                         /* need to handle fieldrefs */
1644                         if (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF) {
1645                                 field = mono_field_from_memberref (image, token, &klass);
1646                                 mono_class_init (klass);
1647                         } else {
1648                                 klass = mono_class_get (image, 
1649                                         MONO_TOKEN_TYPE_DEF | mono_metadata_typedef_from_field (image, token & 0xffffff));
1650                                 mono_class_init (klass);
1651                                 field = mono_class_get_field (klass, token);
1652                         }
1653                         g_assert (field);
1654                         
1655                         if (klass->marshalbyref) {
1656                                 t1 = mono_ctree_new (mp, MB_TERM_REMOTE_LDFLDA, sp [0], NULL);
1657                                 t1->data.fi.klass = klass;
1658                                 t1->data.fi.field = field;
1659                         } else {
1660                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1661
1662                                 if (klass->valuetype)
1663                                         t1->data.i = field->offset - sizeof (MonoObject);
1664                                 else 
1665                                         t1->data.i = field->offset;
1666
1667                                 t1 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t1);
1668                         }
1669
1670                         if (!load_addr) 
1671                                 t1 = ctree_create_load (cfg, field->type, t1, &svt, FALSE);
1672                         else
1673                                 svt = VAL_POINTER;
1674
1675                         PUSH_TREE (t1, svt);
1676                         break;
1677                 }
1678                 case CEE_STSFLD: {
1679                         MonoClass *klass;
1680                         MonoClassField *field;
1681                         guint32 token;
1682
1683                         ++ip;
1684                         token = read32 (ip);
1685                         ip += 4;
1686                         --sp;
1687
1688                         /* need to handle fieldrefs */
1689                         if (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF) {
1690                                 field = mono_field_from_memberref (image, token, &klass);
1691                                 mono_class_init (klass);
1692                         } else {
1693                                 klass = mono_class_get (image, 
1694                                         MONO_TOKEN_TYPE_DEF | mono_metadata_typedef_from_field (image, token & 0xffffff));
1695                                 mono_class_init (klass);
1696                                 field = mono_class_get_field (klass, token);
1697
1698                         }
1699                         g_assert (field);
1700
1701                         if (cfg->share_code) {
1702                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1703                                 t1->data.i = field->offset;
1704                                 t1 = mono_ctree_new (mp, MB_TERM_LDSFLDA, t1, NULL);
1705                                 t1->data.klass = klass;
1706                         } else {
1707                                 MonoVTable *vt = mono_class_vtable (cfg->domain, klass);
1708                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
1709                                 t1->data.p = (char*)(vt->data) + field->offset;
1710                         }
1711                         t1 = ctree_create_store (cfg, field->type, t1, *sp, FALSE);
1712
1713                         ADD_TREE (t1, cli_addr);
1714                         break;
1715                 }
1716                 case CEE_STFLD: {
1717                         MonoClass *klass;
1718                         MonoClassField *field;
1719                         guint32 token;
1720
1721                         ++ip;
1722                         token = read32 (ip);
1723                         ip += 4;
1724                         sp -= 2;
1725
1726                         /* need to handle fieldrefs */
1727                         if (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF) {
1728                                 field = mono_field_from_memberref (image, token, &klass);
1729                                 mono_class_init (klass);
1730                         } else {
1731                                 klass = mono_class_get (image, 
1732                                         MONO_TOKEN_TYPE_DEF | mono_metadata_typedef_from_field (image, token & 0xffffff));
1733                                 mono_class_init (klass);
1734                                 field = mono_class_get_field (klass, token);
1735                         }
1736                         g_assert (field);
1737
1738                         if (klass->marshalbyref) {
1739                                 t1 = mono_ctree_new (mp, mono_map_remote_stind_type (field->type), sp [0], sp [1]);
1740                                 t1->data.fi.klass = klass;
1741                                 t1->data.fi.field = field;
1742                         } else {
1743                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1744                                 t1->data.i = klass->valuetype ? field->offset - sizeof (MonoObject) : field->offset;
1745                                 t1 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t1);
1746                                 t1 = ctree_create_store (cfg, field->type, t1, sp [1], FALSE);
1747                         }
1748
1749
1750                         ADD_TREE (t1, cli_addr);
1751                         break;
1752                 }
1753                 case CEE_LDELEMA: {
1754                         MonoClass *class;
1755                         guint32 esize, token;
1756
1757                         ++ip;
1758                         token = read32 (ip);
1759                         ip += 4;
1760                         sp -= 2;
1761
1762                         class = mono_class_get (image, token);
1763
1764                         mono_class_init (class);
1765
1766                         esize = mono_class_instance_size (class);
1767                         if (class->valuetype)
1768                                 esize -= sizeof (MonoObject);
1769
1770                         t1 = mono_ctree_new (mp, MB_TERM_LDELEMA, sp [0], sp [1]);
1771                         t1->data.i = esize;
1772                         PUSH_TREE (t1, VAL_POINTER);
1773                         break;
1774                 }
1775                 case CEE_NOP: { 
1776                         ++ip;
1777                         break;
1778                 }
1779                 case CEE_BREAK: { 
1780                         ++ip;
1781                         t1 = mono_ctree_new_leaf (mp, MB_TERM_BREAK);
1782                         ADD_TREE (t1, cli_addr);
1783                         break;
1784                 } 
1785                 case CEE_SWITCH: {
1786                         guint32 k, n;
1787                         MonoBBlock **jt;
1788                         gint32 st, target;
1789
1790                         ++ip;
1791                         n = read32 (ip);
1792                         ip += 4;
1793                         --sp;
1794
1795                         t1 = mono_ctree_new (mp, MB_TERM_SWITCH, *sp, NULL);
1796                         jt = t1->data.p = mono_alloc_static (sizeof (gpointer) * (n + 2));
1797                         st = cli_addr + 5 + 4 * n;
1798                         
1799                         // hack: we store n at position 0
1800                         jt [0] = (MonoBBlock *)n;
1801
1802                         create_outstack (cfg, bb, stack, sp - stack);
1803
1804                         for (k = 1; k <= (n + 1); k++) {
1805                                 if (k > n)
1806                                         target = st;
1807                                 else {
1808                                         target = read32 (ip) + st;
1809                                         ip += 4;
1810                                 }
1811                                 g_assert (target >= 0 && target <= header->code_size);
1812                                 g_assert (bcinfo [target].is_block_start);
1813                                 tbb = &cfg->bblocks [bcinfo [target].block_id];
1814                                 mark_reached (cfg, tbb, stack, sp - stack);
1815                                 jt [k] = tbb; 
1816                         }
1817
1818                         ADD_TREE (t1, cli_addr);
1819                         break;
1820                 }
1821                 case CEE_LDTOKEN: {
1822                         gpointer handle;
1823                         MonoClass *handle_class;
1824
1825                         ++ip;
1826                         handle = mono_ldtoken (image, read32 (ip), &handle_class);
1827                         ip += 4;
1828
1829                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1830                         t1->data.p = handle;
1831                         PUSH_TREE (t1, VAL_POINTER);
1832
1833                         break;
1834                 }
1835                 case CEE_NEWARR: {
1836                         MonoClass *class;
1837                         guint32 token;
1838
1839                         ip++;
1840                         --sp;
1841                         token = read32 (ip);
1842                         class = mono_class_get (image, token);
1843                         ip += 4;
1844
1845                         if (cfg->share_code) {
1846                                 t1 = mono_ctree_new (mp, MB_TERM_NEWARR, *sp, NULL);
1847                                 t1->data.p = class;
1848                         }
1849                         else {
1850                                 MonoClass  *ac = mono_array_class_get (&class->byval_arg, 1);
1851                                 MonoVTable *vt = mono_class_vtable (cfg->domain, ac);
1852
1853                                 t1 = mono_ctree_new (mp, MB_TERM_NEWARR_SPEC, *sp, NULL);
1854                                 t1->data.p = vt;
1855                         }
1856
1857                         PUSH_TREE (t1, VAL_POINTER);
1858                         break;
1859                 }
1860                 case CEE_CPOBJ: {
1861                         MonoClass *class;
1862                         guint32 token;
1863
1864                         ++ip;
1865                         token = read32 (ip);
1866                         class = mono_class_get (image, token);
1867                         ip += 4;
1868                         sp -= 2;
1869
1870                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1871                         t1->data.i = mono_class_value_size (class, NULL);                       
1872                         t1 = mono_ctree_new (mp, MB_TERM_CPSRC, sp [1], t1);
1873                         t1 = mono_ctree_new (mp, MB_TERM_CPBLK, sp [0], t1);
1874                         ADD_TREE (t1, cli_addr);
1875                         
1876                         break;
1877                 }
1878                 case CEE_NEWOBJ: {
1879                         MonoMethodSignature *csig;
1880                         MonoMethod *cm;
1881                         MBTree *this = NULL;
1882                         guint32 token;
1883                         int k, align, size, args_size = 0;
1884                         int newarr = FALSE;
1885                         int newstr = FALSE;
1886
1887                         ++ip;
1888                         token = read32 (ip);
1889                         ip += 4;
1890
1891                         cm = mono_get_method (image, token, NULL);
1892                         g_assert (cm);
1893                         g_assert (!strcmp (cm->name, ".ctor"));
1894                         
1895                         csig = cm->signature;
1896                         g_assert (csig->call_convention == MONO_CALL_DEFAULT);
1897                         g_assert (csig->hasthis);
1898                         
1899                         arg_sp = sp -= csig->param_count;
1900
1901                         if (!cm->klass->inited)
1902                                 mono_class_init (cm->klass);
1903
1904                         if (cm->klass->parent == mono_defaults.array_class) {
1905                                 newarr = TRUE;
1906                                 this = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1907                                 this->data.m = cm;
1908                         } else if (cm->klass == mono_defaults.string_class) {
1909                                 newstr = TRUE;
1910                                 this = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1911                                 this->data.m = cm;
1912                         } else {                                
1913                                 if (cm->klass->valuetype) {
1914                                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1915                                         t1->data.i = mono_class_value_size (cm->klass, NULL);
1916                                         this = mono_ctree_new (mp, MB_TERM_LOCALLOC, t1, NULL);
1917                                         this->data.i = TRUE;
1918                                 } else if (cfg->share_code) {
1919                                         this = mono_ctree_new_leaf (mp, MB_TERM_NEWOBJ);
1920                                         this->data.klass = cm->klass;
1921                                 } else {
1922                                         MonoVTable *vt = mono_class_vtable (cfg->domain, cm->klass);
1923                                         this = mono_ctree_new_leaf (mp, MB_TERM_NEWOBJ_SPEC);
1924                                         this->data.p = vt;
1925                                 }
1926
1927                                 this->svt = VAL_POINTER;
1928
1929                                 t1 = mono_store_tree (cfg, -1, this, &this);
1930                                 g_assert (t1);
1931                                 ADD_TREE (t1, cli_addr);
1932                         }
1933                         
1934                         args_size += sizeof (gpointer); /* this argument */             
1935
1936                         for (k = csig->param_count - 1; k >= 0; k--) {
1937                                 MonoType *type = cm->signature->params [k];
1938
1939                                 size = mono_type_stack_size (type, &align);
1940                                 t1 = mono_ctree_new (mp, mono_map_arg_type (type), arg_sp [k], NULL);   
1941                                 t1->data.i = size;
1942                                 ADD_TREE (t1, cli_addr);
1943                                 args_size += size;
1944                         }
1945
1946
1947                         if (newarr || newstr) {
1948
1949                                 t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1950                                 if (newarr) {
1951                                         t2->data.p = mono_array_new_va;
1952                                 } else {
1953                                         t2->data.p = arch_create_jit_trampoline (cm);
1954                                 }
1955
1956                                 t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, this, t2);
1957                                 t1->data.ci.args_size = args_size;
1958                                 t1->data.ci.vtype_num = 0;
1959                                 
1960                                 t1->svt = VAL_POINTER;
1961
1962                                 t1 = mono_store_tree (cfg, -1, t1, &t2);
1963                                 g_assert (t1);
1964                                 ADD_TREE (t1, cli_addr);
1965                                 PUSH_TREE (t2, t2->svt);
1966
1967                         } else {
1968
1969                                 t2 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
1970                                 t2->data.p = arch_create_jit_trampoline (cm);
1971
1972                                 t1 = mono_ctree_new (mp, mono_map_call_type (csig->ret, &svt), this, t2);
1973                                 t1->data.ci.args_size = args_size;
1974                                 t1->data.ci.vtype_num = 0;
1975                                 t1->svt = svt;
1976
1977                                 ADD_TREE (t1, cli_addr);
1978
1979                                 t1 = ctree_create_dup (mp, this);       
1980                                 
1981                                 if (cm->klass->valuetype) {
1982                                         t2 = ctree_create_load (cfg, &cm->klass->byval_arg, t1, &svt, FALSE);
1983                                         PUSH_TREE (t2, svt);
1984                                 } else {
1985                                         PUSH_TREE (t1, t1->svt);
1986                                 }
1987                         }
1988                         break;
1989                 }
1990                 case CEE_CALLI: 
1991                 case CEE_CALL: 
1992                 case CEE_CALLVIRT: {
1993                         MonoMethodSignature *csig;
1994                         MonoMethod *cm;
1995                         MBTree *ftn, *this = NULL;
1996                         guint32 token;
1997                         int k, align, size, args_size = 0;
1998                         int virtual = *ip == CEE_CALLVIRT;
1999                         int calli = *ip == CEE_CALLI;
2000                         gboolean array_set = FALSE;
2001                         gboolean array_get = FALSE;
2002                         /* fixme: compute this value */
2003                         gboolean shared_to_unshared_call = FALSE;
2004                         int nargs, vtype_num = 0;
2005
2006                         ++ip;
2007                         token = read32 (ip);
2008                         ip += 4;
2009
2010                         if (calli) {
2011                                 ftn = *(--sp);
2012                                 csig = mono_metadata_parse_signature (image, token);
2013                                 g_assert (csig);
2014                                 arg_sp = sp -= csig->param_count;
2015                         } else {
2016                                 cm = mono_get_method (image, token, NULL);
2017                                 g_assert (cm);
2018
2019                                 if (cm->klass == mono_defaults.math_class &&
2020                                     cm->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
2021
2022                                         if (!strcmp (cm->name, "Sin")) {
2023                                                 --sp;
2024                                                 t1 = mono_ctree_new (mp, MB_TERM_SIN, *sp, NULL);
2025                                                 PUSH_TREE (t1, VAL_DOUBLE);
2026                                                 break;
2027                                         } else if (!strcmp (cm->name, "Cos")) {
2028                                                 --sp;
2029                                                 t1 = mono_ctree_new (mp, MB_TERM_COS, *sp, NULL);
2030                                                 PUSH_TREE (t1, VAL_DOUBLE);
2031                                                 break;
2032                                         } else if (!strcmp (cm->name, "Sqrt")) {
2033                                                 --sp;
2034                                                 t1 = mono_ctree_new (mp, MB_TERM_SQRT, *sp, NULL);
2035                                                 PUSH_TREE (t1, VAL_DOUBLE);
2036                                                 break;
2037                                         }
2038                                 }
2039
2040                                 if (cm->klass == mono_defaults.string_class &&
2041                                     *cm->name == '.' && !strcmp (cm->name, ".ctor"))
2042                                         g_assert_not_reached ();
2043                                 arg_sp = sp -= cm->signature->param_count;
2044
2045                                 if ((cm->flags & METHOD_ATTRIBUTE_FINAL && 
2046                                      cm->klass != mono_defaults.object_class) ||
2047                                     !(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
2048                                         virtual = 0;
2049                         }
2050
2051                         if (!calli && mono_jit_inline_code && !virtual && cm->inline_count != -1 &&
2052                             (cm->inline_info || check_inlining (cm) >= 0)) {
2053                                 MonoInlineInfo *ii = alloca (sizeof (MonoInlineInfo));
2054                                 int args;
2055
2056                                 mono_jit_stats.inlined_methods++;
2057                                 
2058                                 if (cm->signature->hasthis)
2059                                         sp--;
2060
2061                                 args = cm->signature->param_count + cm->signature->hasthis;
2062
2063                                 ii->method = cm;
2064                                 ii->saved_ip = ip;
2065                                 ii->saved_image = image;
2066                                 ii->arg_map = alloca (args * sizeof (MBTree *));
2067                                 memcpy (ii->arg_map, sp, args * sizeof (MBTree *));
2068
2069                                 if (cm->signature->hasthis && !cm->uses_this && 
2070                                     (ii->arg_map [0]->op != MB_TERM_CHECKTHIS)) {
2071                                         ii->arg_map [0] = mono_ctree_new (mp, MB_TERM_CHECKTHIS, 
2072                                                                           ii->arg_map [0], NULL);
2073                                         ADD_TREE (ii->arg_map [0], cli_addr);
2074                                 }
2075                                 
2076                                 if (cm->inline_count) {
2077                                         inline_list = g_list_prepend (inline_list, ii);
2078                                         ip = ((MonoMethodNormal *)cm)->header->code;
2079                                         ii->end = ip + cm->inline_count;
2080                                         arg_map = ii->arg_map;
2081                                         image = cm->klass->image;
2082                                 }
2083                                 continue;
2084                         }
2085                         
2086                         if (!calli)
2087                                 csig = cm->signature;
2088
2089                         nargs = csig->param_count;
2090                         g_assert (csig->call_convention == MONO_CALL_DEFAULT);
2091                         g_assert (!virtual || csig->hasthis);
2092
2093                         if (!calli && cm->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
2094                                 if (cm->klass->parent == mono_defaults.array_class) {
2095                                         if (!strcmp (cm->name, "Set")) { 
2096                                                 array_set = TRUE;
2097                                                 nargs--;
2098                                         } else if (!strcmp (cm->name, "Get")) 
2099                                                 array_get = TRUE;
2100                                 }
2101                         }
2102
2103                         for (k = nargs - 1; k >= 0; k--) {
2104                                 MonoType *type = csig->params [k];
2105                                 t1 = mono_ctree_new (mp, mono_map_arg_type (type), arg_sp [k], NULL);
2106                                 size = mono_type_stack_size (type, &align);
2107                                 t1->data.i = size;
2108                                 ADD_TREE (t1, cli_addr);
2109                                 args_size += size;
2110                                 // fixme: align value type arguments  to 8 byte boundary on the stack
2111                         }
2112
2113                         if (csig->hasthis) {
2114                                 this = *(--sp);         
2115                                 args_size += sizeof (gpointer);
2116                         } else
2117                                 this = mono_ctree_new_leaf (mp, MB_TERM_NOP);
2118
2119                         if (ISSTRUCT (csig->ret)) {
2120                                 size = mono_type_size (csig->ret, &align);
2121                                 vtype_num = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, VAL_UNKNOWN);
2122                         }
2123
2124                         if (array_get) {
2125                                 int vnum;
2126                                 
2127                                 t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
2128                                 t2->data.p = ves_array_element_address;
2129
2130                                 t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, this, t2);
2131                                 t1->data.ci.args_size = args_size;
2132                                 t1->data.ci.vtype_num = vtype_num;
2133  
2134                                 t1 = mono_ctree_new (mp, mono_map_ldind_type (csig->ret, &svt), t1, NULL);
2135                                 t1->svt = svt;          
2136
2137                                 mono_get_val_sizes (t1->svt, &size, &align);
2138                                 vnum = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, svt);
2139
2140                                 t2 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2141                                 t2->data.i = vnum;
2142                                 t1 = mono_ctree_new (mp, mono_map_store_svt_type (svt), t2, t1);
2143                                 t1->svt = svt;
2144
2145                                 ADD_TREE (t1, cli_addr);
2146                                 t1 = ctree_create_dup (mp, t1);
2147                                 PUSH_TREE (t1, t1->svt);
2148
2149                         } else if (array_set) {
2150
2151                                 t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
2152                                 t2->data.p = ves_array_element_address;
2153
2154                                 t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, this, t2);
2155                                 t1->data.ci.args_size = args_size;
2156                                 t1->data.ci.vtype_num = vtype_num;
2157
2158                                 t1 = ctree_create_store (cfg, csig->params [nargs], t1, arg_sp [nargs], FALSE);
2159                                 ADD_TREE (t1, cli_addr);
2160                         
2161                         } else {
2162
2163                                 if (calli) {
2164                                         t2 = ftn; 
2165                                 } else if (virtual || (csig->hasthis && 
2166                                                 !(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) &&
2167                                                 (cm->klass->marshalbyref || shared_to_unshared_call))) {
2168
2169                                         mono_class_init (cm->klass);
2170                                         
2171                                         if (cm->klass->flags & TYPE_ATTRIBUTE_INTERFACE)
2172                                                 t2 = mono_ctree_new_leaf (mp, MB_TERM_INTF_ADDR);
2173                                         else 
2174                                                 t2 = mono_ctree_new_leaf (mp, MB_TERM_VFUNC_ADDR);
2175          
2176                                         t2->data.m = cm;
2177
2178                                 } else {
2179                                         t2 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
2180                                         t2->data.p = arch_create_jit_trampoline (cm);
2181                                 }
2182
2183                                 t1 = mono_ctree_new (mp, mono_map_call_type (csig->ret, &svt), this, t2);
2184                                 t1->data.ci.args_size = args_size;
2185                                 t1->data.ci.vtype_num = vtype_num;
2186                                 t1->svt = svt;
2187
2188                                 if (csig->ret->type != MONO_TYPE_VOID) {
2189
2190                                         if (vtype_num) {
2191                                                 ADD_TREE (t1, cli_addr);
2192                                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2193                                                 t1->data.i = vtype_num;
2194                                                 PUSH_TREE (t1, VAL_POINTER); 
2195                                         } else {
2196                                                 t1 = mono_store_tree (cfg, -1, t1, &t2);
2197                                                 g_assert (t1);
2198                                                 ADD_TREE (t1, cli_addr);
2199                                                 PUSH_TREE (t2, t2->svt);
2200                                         }
2201                                 } else
2202                                         ADD_TREE (t1, cli_addr);
2203    
2204                         }
2205
2206                         break;
2207                 }
2208                 case CEE_ISINST: {
2209                         MonoClass *c;
2210                         guint32 token;
2211                         ++ip;
2212                         token = read32 (ip);
2213                         --sp;
2214
2215                         c = mono_class_get (image, token);
2216                         if (!c->inited)
2217                                 mono_class_init (c);
2218
2219                         t1 = mono_ctree_new (mp, MB_TERM_ISINST, *sp, NULL);
2220                         t1->data.klass = c;
2221                         
2222                         PUSH_TREE (t1, VAL_POINTER);
2223
2224                         ip += 4;
2225                         break;
2226                 }
2227                 case CEE_CASTCLASS: {
2228                         MonoClass *c;
2229                         guint32 token;
2230                         ++ip;
2231                         token = read32 (ip);
2232                         --sp;
2233
2234                         c = mono_class_get (image, token);
2235                         if (!c->inited)
2236                                 mono_class_init (c);
2237
2238                         t1 = mono_ctree_new (mp, MB_TERM_CASTCLASS, *sp, NULL);
2239                         t1->data.klass = c;
2240                         
2241                         PUSH_TREE (t1, VAL_POINTER);
2242
2243                         ip += 4;
2244                         break;
2245                 }
2246                 case CEE_LDC_I4_S: { 
2247                         ++ip;
2248                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
2249                         t1->data.i = *(const gint8 *)ip;
2250                         ++ip;
2251                         PUSH_TREE (t1, VAL_I32);
2252                         break;
2253                 }
2254                 case CEE_LDC_I4: { 
2255                         ++ip;
2256                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
2257                         t1->data.i = read32 (ip);
2258                         ip += 4;
2259                         PUSH_TREE (t1, VAL_I32);
2260                         break;
2261                 }
2262                 case CEE_LDC_I4_M1:
2263                 case CEE_LDC_I4_0:
2264                 case CEE_LDC_I4_1:
2265                 case CEE_LDC_I4_2:
2266                 case CEE_LDC_I4_3:
2267                 case CEE_LDC_I4_4:
2268                 case CEE_LDC_I4_5:
2269                 case CEE_LDC_I4_6:
2270                 case CEE_LDC_I4_7:
2271                 case CEE_LDC_I4_8: {
2272                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
2273                         t1->data.i = (*ip) - CEE_LDC_I4_0;
2274                         ++ip;
2275                         PUSH_TREE (t1, VAL_I32);
2276                         break;
2277                 }
2278                 case CEE_LDNULL: {
2279                         //fixme: don't know if this is portable ?
2280                         ++ip;
2281                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
2282                         t1->data.i = 0;
2283                         PUSH_TREE (t1, VAL_POINTER);
2284                         break;
2285                 }
2286                 case CEE_LDC_I8: {
2287                         ++ip;
2288                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I8);
2289                         t1->data.l = read64 (ip);
2290                         ip += 8;
2291                         PUSH_TREE (t1, VAL_I64);                
2292                         break;
2293                 }
2294                 case CEE_LDC_R4: {
2295                         float *f = mono_alloc_static (sizeof (float));
2296                         ++ip;
2297                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_R4);
2298                         readr4 (ip, f);
2299                         t1->data.p = f;
2300                         ip += 4;
2301                         PUSH_TREE (t1, VAL_DOUBLE);             
2302                         break;
2303                 }
2304                 case CEE_LDC_R8: { 
2305                         double *d = mono_alloc_static (sizeof (double));
2306                         ++ip;
2307                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_R8);
2308                         readr8 (ip, d);
2309                         t1->data.p = d;
2310                         ip += 8;
2311                         PUSH_TREE (t1, VAL_DOUBLE);             
2312                         break;
2313                 }
2314                 case CEE_LDLOC_0:
2315                 case CEE_LDLOC_1:
2316                 case CEE_LDLOC_2:
2317                 case CEE_LDLOC_3: {
2318                         int n = (*ip) - CEE_LDLOC_0;
2319                         ++ip;
2320
2321                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2322                         t1->data.i = LOCAL_POS (n);
2323                         if (!ISSTRUCT (LOCAL_TYPE (n))) 
2324                                 t1 = ctree_create_load (cfg, LOCAL_TYPE (n), t1, &svt, FALSE);
2325
2326                         PUSH_TREE (t1, svt);
2327                         break;
2328                 }
2329                 case CEE_LDLOC_S: {
2330                         ++ip;
2331                         
2332                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2333                         t1->data.i = LOCAL_POS (*ip);
2334                         if (!ISSTRUCT (LOCAL_TYPE (*ip))) 
2335                                 t1 = ctree_create_load (cfg, LOCAL_TYPE (*ip), t1, &svt, FALSE);
2336                         ++ip;
2337
2338                         PUSH_TREE (t1, svt);
2339                         break;
2340                 }
2341                 case CEE_LDLOCA_S: {
2342                         ++ip;
2343
2344                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2345                         t1->data.i = LOCAL_POS (*ip);
2346                         VARINFO (cfg, t1->data.i).isvolatile = 1;
2347                         ++ip;
2348                         PUSH_TREE (t1, VAL_POINTER);                    
2349                         break;
2350                 }
2351                 case CEE_STLOC_0:
2352                 case CEE_STLOC_1:
2353                 case CEE_STLOC_2:
2354                 case CEE_STLOC_3: {
2355                         int n = (*ip) - CEE_STLOC_0;
2356                         ++ip;
2357                         --sp;
2358
2359                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2360                         t1->data.i = LOCAL_POS (n);
2361
2362                         if ((t2 = mono_stack_duplicate_used_var (cfg, stack, sp, t1->data.i)))
2363                                 ADD_TREE (t2, cli_addr); 
2364
2365                         t1 = ctree_create_store (cfg, LOCAL_TYPE (n), t1, *sp, FALSE);
2366                         ADD_TREE (t1, cli_addr);                        
2367                         break;
2368                 }
2369                 case CEE_STLOC_S: {
2370                         ++ip;
2371                         --sp;
2372
2373                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2374                         t1->data.i = LOCAL_POS (*ip);
2375                         if ((t2 = mono_stack_duplicate_used_var (cfg, stack, sp, t1->data.i)))
2376                                 ADD_TREE (t2, cli_addr); 
2377
2378                         t1 = ctree_create_store (cfg, LOCAL_TYPE (*ip), t1, *sp, FALSE);
2379                         ++ip;
2380                         ADD_TREE (t1, cli_addr);                        
2381                         break;
2382                 }
2383
2384                 case CEE_ADD: {
2385                         ++ip;
2386                         sp -= 2;
2387                         if (sp [0]->op == MB_TERM_CONST_I4 && sp [1]->op == MB_TERM_CONST_I4)
2388                                 t1 = mono_ctree_new_icon4 (mp, sp [0]->data.i + sp [1]->data.i);
2389                         else
2390                                 t1 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], sp [1]);
2391                         PUSH_TREE (t1, sp [0]->svt);
2392                         break;                        
2393                 }
2394
2395                 case CEE_SUB: {
2396                         ++ip;
2397                         sp -= 2;
2398                         if (sp [0]->op == MB_TERM_CONST_I4 && sp [1]->op == MB_TERM_CONST_I4)
2399                                 t1 = mono_ctree_new_icon4 (mp, sp [0]->data.i - sp [1]->data.i);
2400                         else
2401                                 t1 = mono_ctree_new (mp, MB_TERM_SUB, sp [0], sp [1]);
2402                         PUSH_TREE (t1, sp [0]->svt);
2403                         break;                        
2404                 }
2405
2406                 case CEE_AND: {
2407                         ++ip;
2408                         sp -= 2;
2409                         if (sp [0]->op == MB_TERM_CONST_I4 && sp [1]->op == MB_TERM_CONST_I4)
2410                                 t1 = mono_ctree_new_icon4 (mp, sp [0]->data.i & sp [1]->data.i);
2411                         else
2412                                 t1 = mono_ctree_new (mp, MB_TERM_AND, sp [0], sp [1]);
2413                         PUSH_TREE (t1, sp [0]->svt);
2414                         break;                        
2415                 }
2416
2417                 case CEE_OR: {
2418                         ++ip;
2419                         sp -= 2;
2420                         if (sp [0]->op == MB_TERM_CONST_I4 && sp [1]->op == MB_TERM_CONST_I4)
2421                                 t1 = mono_ctree_new_icon4 (mp, sp [0]->data.i | sp [1]->data.i);
2422                         else
2423                                 t1 = mono_ctree_new (mp, MB_TERM_OR, sp [0], sp [1]);
2424                         PUSH_TREE (t1, sp [0]->svt);
2425                         break;                        
2426                 }
2427
2428                 case CEE_XOR: {
2429                         ++ip;
2430                         sp -= 2;
2431                         if (sp [0]->op == MB_TERM_CONST_I4 && sp [1]->op == MB_TERM_CONST_I4)
2432                                 t1 = mono_ctree_new_icon4 (mp, sp [0]->data.i ^ sp [1]->data.i);
2433                         else
2434                                 t1 = mono_ctree_new (mp, MB_TERM_XOR, sp [0], sp [1]);
2435                         PUSH_TREE (t1, sp [0]->svt);
2436                         break;                        
2437                 }
2438
2439                 case CEE_MUL: {
2440                         ++ip;
2441                         sp -= 2;
2442                         if (sp [0]->op == MB_TERM_CONST_I4 && sp [1]->op == MB_TERM_CONST_I4) {
2443                                 t1 = mono_ctree_new_icon4 (mp, sp [0]->data.i * sp [1]->data.i);
2444                                 PUSH_TREE (t1, sp [0]->svt);
2445                         } else {
2446                                 MAKE_SPILLED_BI_ALU1 (MUL, sp [0], sp [1])
2447                         }
2448                         break;                        
2449                 }
2450
2451                 case CEE_DIV: {
2452                         ++ip;
2453                         sp -= 2;
2454                         if (sp [0]->op == MB_TERM_CONST_I4 && sp [1]->op == MB_TERM_CONST_I4) {
2455                                 t1 = mono_ctree_new_icon4 (mp, sp [0]->data.i / sp [1]->data.i);
2456                                 PUSH_TREE (t1, sp [0]->svt);
2457                         } else {
2458                                 MAKE_SPILLED_BI_ALU1 (DIV, sp [0], sp [1])
2459                         }
2460                         break;                        
2461                 }
2462
2463                 case CEE_REM: {
2464                         ++ip;
2465                         sp -= 2;
2466                         if (sp [0]->op == MB_TERM_CONST_I4 && sp [1]->op == MB_TERM_CONST_I4) {
2467                                 t1 = mono_ctree_new_icon4 (mp, sp [0]->data.i % sp [1]->data.i);
2468                                 PUSH_TREE (t1, sp [0]->svt);
2469                         } else {
2470                                 MAKE_SPILLED_BI_ALU1 (REM, sp [0], sp [1])
2471                         }
2472                         break;                        
2473                 }
2474
2475                 case CEE_SHL: {
2476                         ++ip;
2477                         sp -= 2;
2478                         if (sp [0]->op == MB_TERM_CONST_I4 && sp [1]->op == MB_TERM_CONST_I4) {
2479                                 t1 = mono_ctree_new_icon4 (mp, sp [0]->data.i << sp [1]->data.i);
2480                                 PUSH_TREE (t1, sp [0]->svt);
2481                         } else {
2482                                 MAKE_SPILLED_BI_ALU1 (SHL, sp [0], sp [1])
2483                         }
2484                         break;                        
2485                 }
2486
2487                 case CEE_SHR: {
2488                         ++ip;
2489                         sp -= 2;
2490                         if (sp [0]->op == MB_TERM_CONST_I4 && sp [1]->op == MB_TERM_CONST_I4) {
2491                                 t1 = mono_ctree_new_icon4 (mp, sp [0]->data.i >> sp [1]->data.i);
2492                                 PUSH_TREE (t1, sp [0]->svt);
2493                         } else {
2494                                 MAKE_SPILLED_BI_ALU1 (SHR, sp [0], sp [1])
2495                         }
2496                         break;                        
2497                 }
2498
2499                 MAKE_BI_ALU (ADD_OVF)
2500                 MAKE_BI_ALU (ADD_OVF_UN)
2501                 MAKE_BI_ALU (SUB_OVF)
2502                 MAKE_BI_ALU (SUB_OVF_UN)
2503                 MAKE_SPILLED_BI_ALU (SHR_UN)
2504                 MAKE_SPILLED_BI_ALU (MUL_OVF)
2505                 MAKE_SPILLED_BI_ALU (MUL_OVF_UN)
2506                 MAKE_SPILLED_BI_ALU (DIV_UN)
2507                 MAKE_SPILLED_BI_ALU (REM_UN)
2508
2509                 MAKE_LDIND (LDIND_I1,  MB_TERM_LDIND_I1, VAL_I32)
2510                 MAKE_LDIND (LDIND_U1,  MB_TERM_LDIND_U1, VAL_I32)
2511                 MAKE_LDIND (LDIND_I2,  MB_TERM_LDIND_I2, VAL_I32)
2512                 MAKE_LDIND (LDIND_U2,  MB_TERM_LDIND_U2, VAL_I32)
2513                 MAKE_LDIND (LDIND_I,   MB_TERM_LDIND_I4, VAL_I32)
2514                 MAKE_LDIND (LDIND_I4,  MB_TERM_LDIND_I4, VAL_I32)
2515                 MAKE_LDIND (LDIND_REF, MB_TERM_LDIND_REF, VAL_POINTER)
2516                 MAKE_LDIND (LDIND_U4,  MB_TERM_LDIND_U4, VAL_I32)
2517                 MAKE_LDIND (LDIND_I8,  MB_TERM_LDIND_I8, VAL_I64)
2518                 MAKE_LDIND (LDIND_R4,  MB_TERM_LDIND_R4, VAL_DOUBLE)
2519                 MAKE_LDIND (LDIND_R8,  MB_TERM_LDIND_R8, VAL_DOUBLE)
2520
2521                 MAKE_STIND (STIND_I1,  MB_TERM_STIND_I1)
2522                 MAKE_STIND (STIND_I2,  MB_TERM_STIND_I2)
2523                 MAKE_STIND (STIND_I,   MB_TERM_STIND_I4)
2524                 MAKE_STIND (STIND_I4,  MB_TERM_STIND_I4)
2525                 MAKE_STIND (STIND_I8,  MB_TERM_STIND_I8)
2526                 MAKE_STIND (STIND_R4,  MB_TERM_STIND_R4)
2527                 MAKE_STIND (STIND_R8,  MB_TERM_STIND_R8)
2528                 MAKE_STIND (STIND_REF, MB_TERM_STIND_REF)
2529
2530                 MAKE_LDELEM (LDELEM_I1,  MB_TERM_LDIND_I1, VAL_I32, 1)
2531                 MAKE_LDELEM (LDELEM_U1,  MB_TERM_LDIND_U1, VAL_I32, 1)
2532                 MAKE_LDELEM (LDELEM_I2,  MB_TERM_LDIND_I2, VAL_I32, 2)
2533                 MAKE_LDELEM (LDELEM_U2,  MB_TERM_LDIND_U2, VAL_I32, 2)
2534                 MAKE_LDELEM (LDELEM_I,   MB_TERM_LDIND_I4, VAL_I32, 4)
2535                 MAKE_LDELEM (LDELEM_I4,  MB_TERM_LDIND_I4, VAL_I32, 4)
2536                 MAKE_LDELEM (LDELEM_REF, MB_TERM_LDIND_REF, VAL_POINTER, sizeof (gpointer))
2537                 MAKE_LDELEM (LDELEM_U4,  MB_TERM_LDIND_U4, VAL_I32, 4)
2538                 MAKE_LDELEM (LDELEM_I8,  MB_TERM_LDIND_I8, VAL_I64, 8)
2539                 MAKE_LDELEM (LDELEM_R4,  MB_TERM_LDIND_R4, VAL_DOUBLE, 4)
2540                 MAKE_LDELEM (LDELEM_R8,  MB_TERM_LDIND_R8, VAL_DOUBLE, 8)
2541
2542                 MAKE_STELEM (STELEM_I1,  MB_TERM_STIND_I1, 1)
2543                 MAKE_STELEM (STELEM_I2,  MB_TERM_STIND_I2, 2)
2544                 MAKE_STELEM (STELEM_I4,  MB_TERM_STIND_I4, 4)
2545                 MAKE_STELEM (STELEM_I,   MB_TERM_STIND_I4, 4)
2546                 MAKE_STELEM (STELEM_REF, MB_TERM_STIND_REF, sizeof (gpointer))
2547                 MAKE_STELEM (STELEM_I8,  MB_TERM_STIND_I8, 8)
2548                 MAKE_STELEM (STELEM_R4,  MB_TERM_STIND_R4, 4)
2549                 MAKE_STELEM (STELEM_R8,  MB_TERM_STIND_R8, 8)
2550
2551                 case CEE_NEG: {
2552                         ip++;
2553                         sp--;
2554                         if (sp [0]->op == MB_TERM_CONST_I4)
2555                                 t1 = mono_ctree_new_icon4 (mp, -sp [0]->data.i);
2556                         else
2557                                 t1 = mono_ctree_new (mp, MB_TERM_NEG, sp [0], NULL);
2558                         PUSH_TREE (t1, sp [0]->svt);            
2559                         break;
2560                 }
2561                 case CEE_NOT: {
2562                         ip++;
2563                         sp--;
2564                         if (sp [0]->op == MB_TERM_CONST_I4)
2565                                 t1 = mono_ctree_new_icon4 (mp, ~sp [0]->data.i);
2566                         else
2567                                 t1 = mono_ctree_new (mp, MB_TERM_NOT, sp [0], NULL);
2568                         PUSH_TREE (t1, sp [0]->svt);
2569                         break;
2570                 }
2571                 case CEE_BR: 
2572                 case CEE_BR_S: {
2573                         gint32 target;
2574                         int br_s = (*ip == CEE_BR_S);
2575
2576                         ++ip;
2577                         if (br_s)
2578                                 target = cli_addr + 2 + (signed char) *ip;
2579                         else
2580                                 target = cli_addr + 5 + (gint32) read32(ip);
2581
2582                         g_assert (target >= 0 && target <= header->code_size);
2583                         g_assert (bcinfo [target].is_block_start);
2584                         tbb = &cfg->bblocks [bcinfo [target].block_id];
2585                         create_outstack (cfg, bb, stack, sp - stack);
2586                         mark_reached (cfg, tbb, bb->outstack, bb->outdepth);
2587
2588                         t1 = mono_ctree_new_leaf (mp, MB_TERM_BR);
2589                         t1->data.p = tbb;
2590                         ADD_TREE (t1, cli_addr);
2591
2592                         if (br_s)
2593                                 ++ip;
2594                         else
2595                                 ip += 4;
2596
2597                         superblock_end = TRUE;
2598                         break;
2599                 }
2600                 case CEE_JMP: {
2601                         MonoMethod *cm;
2602                         guint32 token;
2603                         ++ip;
2604                         token = read32 (ip);
2605                         ip += 4;
2606
2607                         cm = mono_get_method (method->klass->image, token, NULL);
2608                         g_assert (cm);
2609
2610                         t1 = mono_ctree_new_leaf (mp, MB_TERM_JMP);
2611                         /* fixme: our magic trampoline code does not work in this case,
2612                          * so I need to compile the method immediately */
2613                         t1->data.p = mono_compile_method (cm);;
2614
2615                         ADD_TREE (t1, cli_addr);
2616                         break;
2617                 }
2618                 case CEE_LEAVE:
2619                 case CEE_LEAVE_S: {
2620                         gint32 target;
2621                         MonoBBlock *hb;
2622                         int leave_s = (*ip == CEE_LEAVE_S);
2623
2624                         ++ip;
2625                         if (leave_s)
2626                                 target = cli_addr + 2 + (signed char) *ip;
2627                         else
2628                                 target = cli_addr + 5 + (gint32) read32(ip);
2629
2630                         g_assert (target >= 0 && target <= header->code_size);
2631                         g_assert (bcinfo [target].is_block_start);
2632                         tbb = &cfg->bblocks [bcinfo [target].block_id];
2633
2634                         /* empty the stack */
2635                         while (sp != stack) {
2636                                 sp--;
2637                                 t1 = mono_ctree_new (mp, MB_TERM_POP, *sp, NULL);
2638                                 ADD_TREE (t1, cli_addr);
2639                         }
2640
2641                         mark_reached (cfg, tbb, NULL, 0);
2642
2643                         /* fixme: fault handler */
2644
2645                         if ((hb = mono_find_final_block (cfg, cli_addr, target, MONO_EXCEPTION_CLAUSE_FINALLY))) {
2646                                 mark_reached (cfg, hb, NULL, 0);
2647                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_HANDLER);
2648                                 t1->data.p = hb;
2649                                 ADD_TREE (t1, cli_addr);
2650                         } 
2651
2652                         t1 = mono_ctree_new_leaf (mp, MB_TERM_BR);
2653                         t1->data.p = tbb;
2654                         ADD_TREE (t1, cli_addr);
2655                         
2656                         if (leave_s)
2657                                 ++ip;
2658                         else
2659                                 ip += 4;
2660
2661                         superblock_end = TRUE;
2662                         break;
2663                 }
2664                 
2665
2666                 MAKE_CJUMP(BGT)
2667                 MAKE_CJUMP(BGT_UN)
2668                 MAKE_CJUMP(BLT)
2669                 MAKE_CJUMP(BLT_UN)
2670                 MAKE_CJUMP(BNE_UN)
2671                 MAKE_CJUMP(BEQ)
2672                 MAKE_CJUMP(BGE)
2673                 MAKE_CJUMP(BGE_UN)
2674                 MAKE_CJUMP(BLE)
2675                 MAKE_CJUMP(BLE_UN)
2676
2677                 case CEE_BRTRUE:
2678                 case CEE_BRTRUE_S: {
2679                         gint32 target;
2680                         int near_jump = *ip == CEE_BRTRUE_S;
2681                         ++ip;
2682                         --sp;
2683
2684                         t1 = mono_ctree_new (mp, MB_TERM_BRTRUE, sp [0], NULL);
2685
2686                         if (near_jump)
2687                                 target = cli_addr + 2 + (signed char) *ip;
2688                         else 
2689                                 target = cli_addr + 5 + (gint32) read32 (ip);
2690
2691                         g_assert (target >= 0 && target <= header->code_size);
2692                         g_assert (bcinfo [target].is_block_start);
2693                         tbb = &cfg->bblocks [bcinfo [target].block_id];
2694                         create_outstack (cfg, bb, stack, sp - stack);
2695                         mark_reached (cfg, tbb, bb->outstack, bb->outdepth);
2696   
2697                         t1->data.p = tbb;
2698                         ip += near_jump ? 1: 4;
2699                         ADD_TREE (t1, cli_addr);
2700                         break;
2701                 }
2702                 case CEE_BRFALSE:
2703                 case CEE_BRFALSE_S: {
2704                         gint32 target;
2705                         int near_jump = *ip == CEE_BRFALSE_S;
2706                         ++ip;
2707                         --sp;
2708
2709                         t1 = mono_ctree_new (mp, MB_TERM_BRFALSE, sp [0], NULL);
2710
2711                         if (near_jump)
2712                                 target = cli_addr + 2 + (signed char) *ip;
2713                         else 
2714                                 target = cli_addr + 5 + (gint32) read32 (ip);
2715
2716                         g_assert (target >= 0 && target <= header->code_size);
2717                         g_assert (bcinfo [target].is_block_start);
2718                         tbb = &cfg->bblocks [bcinfo [target].block_id];
2719                         create_outstack (cfg, bb, stack, sp - stack);
2720                         mark_reached (cfg, tbb, bb->outstack, bb->outdepth);
2721                     
2722                         t1->data.p = tbb;
2723                         ip += near_jump ? 1: 4;
2724                         ADD_TREE (t1, cli_addr);
2725                         break;
2726                 }
2727                 case CEE_RET: {
2728                         MonoType *ret = signature->ret;
2729
2730                         ip++;
2731
2732                         if (ret->type != MONO_TYPE_VOID) {
2733                                 --sp;
2734                                 if (ISSTRUCT (ret)) {
2735                                         int align;
2736                                         t1 = mono_ctree_new (mp, MB_TERM_RET_OBJ, *sp, NULL);
2737                                         t1->data.i = mono_class_value_size (ret->data.klass, &align);
2738                                 } else {
2739                                         t1 = mono_ctree_new (mp, MB_TERM_RET, *sp, NULL);
2740                                 }
2741                         } else {
2742                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_RET_VOID);
2743                         }
2744
2745                         t1->last_instr = (ip == (header->code + header->code_size));
2746
2747                         ADD_TREE (t1, cli_addr);
2748
2749                         if (sp > stack) {
2750                                 g_warning ("more values on stack at IL_%04x: %d",  ip - header->code, sp - stack);
2751                                 mono_print_ctree (cfg, sp [-1]);
2752                                 printf ("\n");
2753                         }
2754                         superblock_end = TRUE;
2755                         break;
2756                 }
2757                 case CEE_ENDFINALLY: {
2758                         ip++;
2759
2760                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ENDFINALLY);
2761                         ADD_TREE (t1, cli_addr);
2762                         t1->last_instr = FALSE;
2763
2764                         g_assert (sp == stack);
2765                         superblock_end = TRUE;
2766                         break;
2767                 }
2768                 case CEE_LDARG_0:
2769                 case CEE_LDARG_1:
2770                 case CEE_LDARG_2:
2771                 case CEE_LDARG_3: {
2772                         int n = (*ip) - CEE_LDARG_0;
2773                         ++ip;
2774
2775                         if (arg_map) {
2776                                 *sp = arg_map [n];
2777                                 sp++;
2778                         } else {
2779                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2780                                 t1->data.i = ARG_POS (n);
2781                                 if (!ISSTRUCT (ARG_TYPE (n))) 
2782                                         t1 = ctree_create_load (cfg, ARG_TYPE (n), t1, &svt, TRUE);
2783                         
2784                                 PUSH_TREE (t1, svt);
2785                         }
2786
2787                         break;
2788                 }
2789                 case CEE_LDARG_S: {
2790                         ++ip;
2791
2792                         if (arg_map) {
2793                                 *sp = arg_map [*ip];
2794                                 sp++;
2795                         } else {
2796                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2797                                 t1->data.i = ARG_POS (*ip);
2798                                 if (!ISSTRUCT (ARG_TYPE (*ip))) 
2799                                         t1 = ctree_create_load (cfg, ARG_TYPE (*ip), t1, &svt, TRUE);
2800                                 PUSH_TREE (t1, svt);
2801                         }
2802                         ++ip;
2803                         break;
2804                 }
2805                 case CEE_LDARGA_S: {
2806                         ++ip;
2807                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2808                         t1->data.i = ARG_POS (*ip);
2809                         PUSH_TREE (t1, VAL_POINTER);
2810                         ++ip;
2811                         break;
2812                 }
2813                 case CEE_STARG_S: {
2814                         ++ip;
2815                         --sp;
2816
2817                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2818                         t1->data.i = ARG_POS (*ip);
2819                         t1 = ctree_create_store (cfg, ARG_TYPE (*ip), t1, *sp, TRUE);
2820                         ++ip;
2821                         ADD_TREE (t1, cli_addr);                        
2822                         break;
2823                 }
2824                 case CEE_DUP: {
2825                         int vnum;
2826
2827                         ++ip; 
2828
2829                         /* fixme: maybe we should add more of these optimisations */
2830                         if (sp [-1]->op == MB_TERM_CONST_I4) {
2831
2832                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
2833                                 t1->data.i = sp [-1]->data.i;
2834                                 PUSH_TREE (t1, VAL_I32);
2835                               
2836                         } else {
2837                                 sp--;
2838
2839                                 vnum = mono_allocate_intvar (cfg, sp - stack, sp [0]->svt);
2840                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2841                                 t1->data.i = vnum;
2842                        
2843                                 t2 = mono_ctree_new (mp, mono_map_store_svt_type (sp [0]->svt), t1, sp [0]);
2844                                 t2->svt = sp [0]->svt;
2845                                 ADD_TREE (t2, cli_addr);
2846
2847                                 t1 = ctree_create_dup (mp, t2);         
2848                                 PUSH_TREE (t1, t1->svt);
2849                                 t1 = ctree_create_dup (mp, t1);         
2850                                 PUSH_TREE (t1, t1->svt);
2851                         }
2852                         break;
2853                 }
2854                 case CEE_POP: {
2855                         ++ip;
2856                         --sp;
2857
2858                         t1 = mono_ctree_new (mp, MB_TERM_POP, *sp, NULL);
2859                         ADD_TREE (t1, cli_addr);
2860
2861                         break;
2862                 }
2863                 case CEE_CKFINITE: {
2864                         int vnum;
2865                         ++ip;
2866                         sp--;
2867
2868                         /* this instr. can throw exceptions as side effect,
2869                          * so we cant eliminate dead code which contains CKFINITE opdodes.
2870                          * Spilling to memory makes sure that we always perform
2871                          * this check */
2872                         vnum = mono_allocate_intvar (cfg, sp - stack, sp [0]->svt);
2873                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2874                         t1->data.i = vnum;
2875                        
2876                         t2 = mono_ctree_new (mp, MB_TERM_CKFINITE, *sp, NULL);
2877
2878                         t2 = mono_ctree_new (mp, mono_map_store_svt_type (sp [0]->svt), t1, t2);
2879                         t2->svt = sp [0]->svt;
2880                         ADD_TREE (t2, cli_addr);
2881
2882                         t1 = ctree_create_dup (mp, t2);         
2883                         PUSH_TREE (t1, t1->svt);
2884                         break;
2885                 }
2886                 case CEE_CONV_U1: 
2887                         ++ip;
2888                         sp--;
2889                         if (sp [0]->op == MB_TERM_CONST_I4)
2890                                 t1 = mono_ctree_new_icon4 (mp, (guint8)sp [0]->data.i);
2891                         else
2892                                 t1 = mono_ctree_new (mp, MB_TERM_CONV_U1, *sp, NULL);
2893                         PUSH_TREE (t1, VAL_I32);                
2894                         break;
2895                 case CEE_CONV_I1:
2896                         ++ip;
2897                         sp--;
2898                         if (sp [0]->op == MB_TERM_CONST_I4)
2899                                 t1 = mono_ctree_new_icon4 (mp, (gint8)sp [0]->data.i);
2900                         else
2901                                 t1 = mono_ctree_new (mp, MB_TERM_CONV_I1, *sp, NULL);
2902                         PUSH_TREE (t1, VAL_I32);                
2903                         break;
2904                 case CEE_CONV_U2: 
2905                         ++ip;
2906                         sp--;
2907                         if (sp [0]->op == MB_TERM_CONST_I4)
2908                                 t1 = mono_ctree_new_icon4 (mp, (guint16)sp [0]->data.i);
2909                         else
2910                                 t1 = mono_ctree_new (mp, MB_TERM_CONV_U2, *sp, NULL);
2911                         PUSH_TREE (t1, VAL_I32);                
2912                         break;
2913                 case CEE_CONV_I2:
2914                         ++ip;
2915                         sp--;
2916                         if (sp [0]->op == MB_TERM_CONST_I4)
2917                                 t1 = mono_ctree_new_icon4 (mp, (gint16)sp [0]->data.i);
2918                         else
2919                                 t1 = mono_ctree_new (mp, MB_TERM_CONV_I2, *sp, NULL);
2920                         PUSH_TREE (t1, VAL_I32);                
2921                         break;
2922                 case CEE_CONV_I: 
2923                 case CEE_CONV_I4:
2924                         ++ip;
2925                         sp--;
2926                         if (sp [0]->op == MB_TERM_CONST_I4)
2927                                 t1 = *sp;
2928                         else
2929                                 t1 = mono_ctree_new (mp, MB_TERM_CONV_I4, *sp, NULL);
2930                         PUSH_TREE (t1, VAL_I32);                
2931                         break;
2932                 case CEE_CONV_U: 
2933                 case CEE_CONV_U4: 
2934                         ++ip;
2935                         sp--;
2936                         if (sp [0]->op == MB_TERM_CONST_I4)
2937                                 t1 = *sp;
2938                         else
2939                                 t1 = mono_ctree_new (mp, MB_TERM_CONV_U4, *sp, NULL);
2940                         PUSH_TREE (t1, VAL_I32);                
2941                         break;
2942                 case CEE_CONV_I8:
2943                         ++ip;
2944                         sp--;
2945                         t1 = mono_ctree_new (mp, MB_TERM_CONV_I8, *sp, NULL);
2946                         PUSH_TREE (t1, VAL_I64);                
2947                         break;
2948                 case CEE_CONV_U8:
2949                         ++ip;
2950                         sp--;
2951                         t1 = mono_ctree_new (mp, MB_TERM_CONV_U8, *sp, NULL);
2952                         PUSH_TREE (t1, VAL_I64);                
2953                         break;
2954                 case CEE_CONV_R8:
2955                         ++ip;
2956                         sp--;
2957                         t1 = mono_ctree_new (mp, MB_TERM_CONV_R8, *sp, NULL);
2958                         PUSH_TREE (t1, VAL_DOUBLE);             
2959                         break;
2960                 case CEE_CONV_R4:
2961                         ++ip;
2962                         sp--;
2963                         t1 = mono_ctree_new (mp, MB_TERM_CONV_R4, *sp, NULL);
2964                         PUSH_TREE (t1, VAL_DOUBLE);             
2965                         break;
2966                 case CEE_CONV_R_UN:
2967                         ++ip;
2968                         sp--;
2969                         t1 = mono_ctree_new (mp, MB_TERM_CONV_R_UN, *sp, NULL);
2970                         PUSH_TREE (t1, VAL_DOUBLE);             
2971                         break;
2972                 case CEE_CONV_OVF_I:
2973                 case CEE_CONV_OVF_I4:
2974                         ++ip;
2975                         sp--;
2976                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_I4, *sp, NULL);
2977                         PUSH_TREE (t1, VAL_I32);
2978                         break;
2979                 case CEE_CONV_OVF_I_UN:
2980                 case CEE_CONV_OVF_I4_UN:
2981                         ++ip;
2982                         sp--;
2983                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_I4_UN, *sp, NULL);
2984                         PUSH_TREE (t1, VAL_I32);                
2985                         break;
2986                 case CEE_CONV_OVF_U:
2987                 case CEE_CONV_OVF_U4:
2988                         ++ip;
2989                         sp--;
2990                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_U4, *sp, NULL);
2991                         PUSH_TREE (t1, VAL_I32);                
2992                         break;
2993                 case CEE_CONV_OVF_I1:
2994                         ++ip;
2995                         sp--;
2996                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_I1, *sp, NULL);
2997                         PUSH_TREE (t1, VAL_I32);
2998                         break;
2999                 case CEE_CONV_OVF_I1_UN:
3000                         ++ip;
3001                         sp--;
3002                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_I1_UN, *sp, NULL);
3003                         PUSH_TREE (t1, VAL_I32);
3004                         break;
3005                 case CEE_CONV_OVF_U1_UN:
3006                         ++ip;
3007                         sp--;
3008                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_U1_UN, *sp, NULL);
3009                         PUSH_TREE (t1, VAL_I32);
3010                         break;
3011                 case CEE_CONV_OVF_U1:
3012                         ++ip;
3013                         sp--;
3014                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_U1, *sp, NULL);
3015                         PUSH_TREE (t1, VAL_I32);
3016                         break;
3017                 case CEE_CONV_OVF_I2:
3018                         ++ip;
3019                         sp--;
3020                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_I2, *sp, NULL);
3021                         PUSH_TREE (t1, VAL_I32);
3022                         break;
3023                 case CEE_CONV_OVF_U2_UN:
3024                         ++ip;
3025                         sp--;
3026                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_U2_UN, *sp, NULL);
3027                         PUSH_TREE (t1, VAL_I32);
3028                         break;
3029                 case CEE_CONV_OVF_U2:
3030                         ++ip;
3031                         sp--;
3032                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_U2, *sp, NULL);
3033                         PUSH_TREE (t1, VAL_I32);
3034                         break;
3035                 case CEE_CONV_OVF_I2_UN:
3036                         ++ip;
3037                         sp--;
3038                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_I2_UN, *sp, NULL);
3039                         PUSH_TREE (t1, VAL_I32);
3040                         break;
3041                 case CEE_CONV_OVF_U8:
3042                         ++ip;
3043                         sp--;
3044                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_U8, *sp, NULL);
3045                         PUSH_TREE (t1, VAL_I32);
3046                         break;
3047                 case CEE_CONV_OVF_U_UN:
3048                 case CEE_CONV_OVF_U4_UN:
3049                         // fixme: raise exceptions ?
3050                         ++ip;
3051                         sp--;
3052                         t1 = mono_ctree_new (mp, MB_TERM_CONV_I4, *sp, NULL);
3053                         PUSH_TREE (t1, VAL_I32);                
3054                         break;
3055                 case CEE_CONV_OVF_I8_UN:
3056                         ++ip;
3057                         sp--;
3058                         t1 = mono_ctree_new (mp, MB_TERM_CONV_OVF_I8_UN, *sp, NULL);
3059                         PUSH_TREE (t1, VAL_I64);
3060                         break;
3061                 case CEE_PREFIX1: {
3062                         ++ip;                   
3063                         switch (*ip) {
3064                                 
3065                         case CEE_LDLOC: {
3066                                 int n;
3067                                 ++ip;
3068                                 n = read16 (ip);
3069
3070                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
3071                                 t1->data.i = LOCAL_POS (n);
3072                                 if (!ISSTRUCT (LOCAL_TYPE (n))) 
3073                                         t1 = ctree_create_load (cfg, LOCAL_TYPE (n), t1, &svt, FALSE);
3074                                 ip += 2;
3075
3076                                 PUSH_TREE (t1, svt);
3077                                 break;
3078                         }
3079                         case CEE_LDLOCA: {
3080                                 ++ip;
3081
3082                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
3083                                 t1->data.i = LOCAL_POS (read16 (ip));
3084                                 VARINFO (cfg, t1->data.i).isvolatile = 1;
3085                                 ip += 2;
3086                                 PUSH_TREE (t1, VAL_POINTER);                    
3087                                 break;
3088                         }
3089                         case CEE_STLOC: {
3090                                 ++ip;
3091                                 --sp;
3092
3093                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
3094                                 t1->data.i = LOCAL_POS (read16 (ip));
3095                                 if ((t2 = mono_stack_duplicate_used_var (cfg, stack, sp, t1->data.i)))
3096                                         ADD_TREE (t2, cli_addr); 
3097
3098                                 t1 = ctree_create_store (cfg, LOCAL_TYPE (read16 (ip)), t1, *sp, FALSE);
3099                                 ip += 2;
3100                                 ADD_TREE (t1, cli_addr);                        
3101                                 break;
3102                         }
3103                         case CEE_STARG: {
3104                                 guint32 arg_pos;
3105                                 ++ip;
3106                                 --sp;
3107
3108                                 arg_pos = read16 (ip);
3109                                 ip += 2;
3110
3111                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
3112                                 t1->data.i = ARG_POS (arg_pos);
3113                                 t1 = ctree_create_store (cfg, ARG_TYPE (arg_pos), t1, *sp, TRUE);
3114                                 ADD_TREE (t1, cli_addr);                        
3115                                 break;
3116                         }
3117
3118                         MAKE_CMP (CEQ)
3119                         MAKE_CMP (CLT)
3120                         MAKE_CMP (CLT_UN)
3121                         MAKE_CMP (CGT)
3122                         MAKE_CMP (CGT_UN)
3123
3124                         case CEE_RETHROW: {
3125                                 ++ip;
3126                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_RETHROW);
3127                                 t1->data.i = mono_allocate_excvar (cfg);
3128                                 ADD_TREE (t1, cli_addr);
3129                                 break;
3130                         }
3131                         case CEE_LDFTN: {
3132                                 MonoMethod *cm;
3133                                 guint32 token;
3134                                 ++ip;
3135                                 token = read32 (ip);
3136                                 ip += 4;
3137
3138                                 cm = mono_get_method (image, token, NULL);
3139                                 g_assert (cm);
3140                                 
3141                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_LDFTN);
3142                                 t1->data.m = cm;
3143                                 PUSH_TREE (t1, VAL_POINTER);
3144                                 break;
3145                         }
3146                         case CEE_LDVIRTFTN: {
3147                                 MonoMethod *cm;
3148                                 guint32 token;
3149                                 ++ip;
3150                                 token = read32 (ip);
3151                                 ip += 4;
3152                                 --sp;
3153
3154                                 cm = mono_get_method (image, token, NULL);
3155                                 g_assert (cm);
3156
3157                                 if (cm->klass->flags & TYPE_ATTRIBUTE_INTERFACE)
3158                                         t2 = mono_ctree_new_leaf (mp, MB_TERM_INTF_ADDR);
3159                                 else 
3160                                         t2 = mono_ctree_new_leaf (mp, MB_TERM_VFUNC_ADDR);
3161
3162                                 t2->data.m = cm;
3163
3164                                 t1 = mono_ctree_new (mp, MB_TERM_LDVIRTFTN, *sp, t2);
3165
3166                                 PUSH_TREE (t1, VAL_POINTER);
3167
3168                                 break;
3169                         }
3170                         case CEE_INITOBJ: {
3171                                 MonoClass *class;
3172                                 guint32 token;
3173                                 
3174                                 ++ip;
3175                                 token = read32 (ip);
3176                                 class = mono_class_get (image, token);
3177                                 ip += 4;
3178                                 sp--;
3179                                 
3180                                 t1 = mono_ctree_new (mp, MB_TERM_INITOBJ, *sp, NULL);
3181                                 t1->data.i = mono_class_value_size (class, NULL);
3182                                 ADD_TREE (t1, cli_addr);
3183
3184                                 break;
3185                         }
3186                         case CEE_LDARG: {
3187                                 guint16 n;
3188                                 ++ip;
3189                                 n = read16 (ip);
3190                                 ip += 2;
3191
3192                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
3193                                 t1->data.i = ARG_POS (n);
3194                                 if (!ISSTRUCT (ARG_TYPE (n))) 
3195                                         t1 = ctree_create_load (cfg, ARG_TYPE (n), t1, &svt, TRUE);
3196                                 PUSH_TREE (t1, svt);
3197                                 break;
3198                         }
3199                         case CEE_LDARGA: {
3200                                 guint16 n;
3201                                 ++ip;
3202                                 n = read16 (ip);
3203                                 ip += 2;
3204
3205                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
3206                                 t1->data.i = ARG_POS (n);
3207                                 PUSH_TREE (t1, svt);
3208                                 break;
3209                         }
3210                         case CEE_SIZEOF: {
3211                                 guint32 token;
3212                                 int align;
3213                                 ++ip;
3214                                 token = read32 (ip);
3215                                 ip += 4;
3216
3217                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
3218                                 if (mono_metadata_token_table (token) == MONO_TABLE_TYPESPEC) {
3219                                         MonoType *type = mono_type_create_from_typespec (image, token);
3220                                         t1->data.i = mono_type_size (type, &align);
3221                                         mono_metadata_free_type (type);
3222                                 } else {
3223                                         MonoClass *szclass = mono_class_get (image, token);
3224                                         mono_class_init (szclass);
3225                                         g_assert (szclass->valuetype);
3226                                         t1->data.i = mono_class_value_size (szclass, &align);
3227                                 }
3228
3229                                 PUSH_TREE (t1, VAL_I32);
3230                                 break;
3231                         }
3232                         case CEE_CPBLK: {
3233                                 ++ip;
3234                                 sp -= 3;
3235
3236                                 t1 = mono_ctree_new (mp, MB_TERM_CPSRC, sp [1], sp [2]);
3237                                 t1 = mono_ctree_new (mp, MB_TERM_CPBLK, sp [0], t1);
3238                                 ADD_TREE (t1, cli_addr);
3239                                 break;
3240                         }
3241                         case CEE_UNALIGNED_: {
3242                                 ++ip;
3243                                 // fixme: implement me
3244                                 break;
3245                         }
3246                         case CEE_VOLATILE_: {
3247                                 ++ip;
3248                                 // fixme: implement me                          
3249                                 break;
3250                         }
3251                         case CEE_LOCALLOC: {
3252                                 ++ip;
3253                                 --sp;
3254
3255                                 t1 = mono_ctree_new (mp, MB_TERM_LOCALLOC, *sp, NULL);
3256                                 t1->data.i = header->init_locals;
3257                                 PUSH_TREE (t1, VAL_POINTER);
3258                                 break;
3259                         }
3260                         case CEE_INITBLK: {
3261                                 ++ip;
3262                                 sp -= 3;
3263
3264                                 t1 = mono_ctree_new (mp, MB_TERM_CPSRC, sp [1], sp [2]);
3265                                 t1 = mono_ctree_new (mp, MB_TERM_INITBLK, sp [0], t1);
3266                                 ADD_TREE (t1, cli_addr);
3267                                 break;
3268                         }
3269                         default:
3270                                 g_error ("Unimplemented opcode at IL_%04x "
3271                                          "0xFE %02x", ip - header->code, *ip);
3272                         }
3273                         break;
3274                 }       
3275                 default:
3276                         g_warning ("unknown instruction `%s' at IL_%04X", 
3277                                    mono_opcode_names [*ip], ip - header->code);
3278                         if (mono_debug_format == MONO_DEBUG_FORMAT_NONE) {
3279                                 return FALSE;
3280                         }
3281                         mono_print_forest (cfg, forest);
3282                         g_assert_not_reached ();
3283                 }
3284         }               
3285
3286         if ((depth = sp - stack)) {
3287                 //printf ("DEPTH %d %d\n",  depth, sp [0]->op);
3288                 //mono_print_forest (cfg, forest);
3289                 create_outstack (cfg, bb, stack, sp - stack);
3290         }
3291
3292                                 } else 
3293                                         superblock_end = TRUE;
3294
3295                         } else {
3296                                 superblock_end = TRUE;
3297                                 //printf ("unreached block %d\n", i);
3298                                 repeat = TRUE;
3299                                 if (repeat_count >= 10) {
3300                                         /*mono_print_forest (cfg, forest);
3301                                         g_warning ("repeat count exceeded at ip: 0x%04x in %s\n", bb->cli_addr, cfg->method->name);*/
3302                                         repeat = FALSE;
3303                                 }
3304                         }
3305                                 //printf ("BBE %d %d %d %d\n", i, bb->reached, bb->finished, superblock_end);
3306                 }
3307
3308                 repeat_count++;
3309                 //printf ("REPEAT %d\n", repeat);
3310                 mono_jit_stats.analyze_stack_repeat++;
3311
3312
3313         } while (repeat);
3314
3315         return TRUE;
3316 }
3317
3318 static void
3319 mono_cfg_free (MonoFlowGraph *cfg)
3320 {
3321         int i;
3322
3323         for (i = 0; i < cfg->block_count; i++) {
3324                 if (!cfg->bblocks [i].reached)
3325                         continue;
3326                 g_ptr_array_free (cfg->bblocks [i].forest, TRUE);
3327                 g_list_free (cfg->bblocks [i].succ);
3328         }
3329
3330         if (cfg->bcinfo)
3331                 g_free (cfg->bcinfo);
3332
3333         if (cfg->bblocks)
3334                 g_free (cfg->bblocks);
3335                 
3336         g_array_free (cfg->varinfo, TRUE);
3337
3338         mono_mempool_destroy (cfg->mp);
3339 }
3340
3341 static MonoFlowGraph *
3342 mono_cfg_new (MonoMethod *method)
3343 {
3344         MonoVarInfo vi;
3345         MonoFlowGraph *cfg;
3346         MonoMemPool *mp = mono_mempool_new ();
3347
3348         g_assert (((MonoMethodNormal *)method)->header);
3349
3350         cfg = mono_mempool_alloc0 (mp, sizeof (MonoFlowGraph));
3351
3352         cfg->domain = mono_domain_get ();
3353         cfg->method = method;
3354         cfg->mp = mp;
3355
3356         /* reserve space for caller saved registers */
3357         /* fixme: this is arch dependent */
3358         /* we save EAX, EDX, ECX - and ESP if we call finally handlers */
3359         cfg->locals_size = 16;
3360
3361         /* fixme: we should also consider loader optimisation attributes */
3362         cfg->share_code = mono_jit_share_code;
3363
3364         cfg->varinfo = g_array_new (FALSE, TRUE, sizeof (MonoVarInfo));
3365         
3366         SET_VARINFO (vi, 0, 0, 0, 0);
3367         g_array_append_val (cfg->varinfo, vi); /* add invalid value at position 0 */
3368
3369         cfg->intvars = mono_mempool_alloc0 (mp, sizeof (guint16) * VAL_DOUBLE * 
3370                                             ((MonoMethodNormal *)method)->header->max_stack);
3371
3372         mono_analyze_flow (cfg);
3373                 
3374         if (!mono_analyze_stack (cfg)) {
3375                 mono_cfg_free (cfg);
3376                 return NULL;
3377         }
3378         
3379         return cfg;
3380 }
3381
3382 static gpointer 
3383 mono_get_runtime_method (MonoMethod* method)
3384 {
3385         const char *name = method->name;
3386         guint8 *addr = NULL;
3387         gboolean delegate = FALSE;
3388
3389         if (method->klass->parent == mono_defaults.multicastdelegate_class)
3390                 delegate = TRUE;
3391                                 
3392         if (delegate && *name == '.' && (strcmp (name, ".ctor") == 0)) {
3393                 addr = (gpointer)mono_delegate_ctor;
3394         } else if (delegate && *name == 'I' && (strcmp (name, "Invoke") == 0)) {
3395                 addr = arch_get_delegate_invoke (method);
3396         } else if (delegate && *name == 'B' && (strcmp (name, "BeginInvoke") == 0)) {
3397                 addr = arch_get_delegate_begin_invoke (method);
3398         } else if (delegate && *name == 'E' && (strcmp (name, "EndInvoke") == 0)) {
3399                 /* this can raise exceptions, so we need a wrapper to save/restore LMF */
3400                 method->addr = (gpointer)arch_end_invoke;
3401                 addr = arch_create_native_wrapper (method);
3402         }
3403
3404         return addr;
3405 }
3406
3407 static int
3408 match_debug_method (MonoMethod* method)
3409 {
3410         GList *tmp = mono_debug_methods;
3411
3412         for (; tmp; tmp = tmp->next) {
3413                 if (mono_method_desc_full_match (tmp->data, method))
3414                         return 1;
3415         }
3416         return 0;
3417 }
3418
3419 /**
3420  * mono_compile_method:
3421  * @method: pointer to the method info
3422  *
3423  * JIT compilation of a single method. 
3424  *
3425  * Returns: a pointer to the newly created code.
3426  */
3427 gpointer
3428 mono_compile_method (MonoMethod *method)
3429 {
3430         MonoDomain *target_domain, *domain = mono_domain_get ();
3431         MonoJitInfo *ji;
3432         guint8 *addr;
3433         GHashTable *jit_code_hash;
3434
3435         if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
3436             (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)) {
3437                 if (!method->info)
3438                         method->info = arch_create_native_wrapper (method);
3439                 return method->info;
3440         }
3441
3442         if (mono_jit_share_code)
3443                 target_domain = mono_root_domain;
3444         else 
3445                 target_domain = domain;
3446
3447         jit_code_hash = target_domain->jit_code_hash;
3448
3449         if ((addr = g_hash_table_lookup (jit_code_hash, method))) {
3450                 mono_jit_stats.methods_lookups++;
3451                 return addr;
3452         }
3453
3454         mono_jit_stats.methods_compiled++;
3455         
3456         if (mono_jit_trace_calls || mono_jit_dump_asm || mono_jit_dump_forest) {
3457                 printf ("Start JIT compilation of %s.%s:%s\n", method->klass->name_space,
3458                         method->klass->name, method->name);
3459         }
3460
3461         if (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME) {
3462                 if (!(addr = mono_get_runtime_method (method))) {       
3463                         mono_profiler_method_end_jit (method, MONO_PROFILE_FAILED);
3464                         if (mono_debug_format != MONO_DEBUG_FORMAT_NONE) 
3465                                 return NULL;
3466
3467                         g_error ("Don't know how to exec runtime method %s.%s::%s", 
3468                                  method->klass->name_space, method->klass->name, method->name);
3469                 }
3470         } else {
3471                 MonoMethodHeader *header = ((MonoMethodNormal *)method)->header;
3472                 MonoFlowGraph *cfg;
3473                 gulong code_size_ratio;
3474         
3475                 mono_profiler_method_jit (method);
3476         
3477                 if (!(cfg = mono_cfg_new (method))) {
3478                         mono_profiler_method_end_jit (method, MONO_PROFILE_FAILED);
3479                         return NULL;
3480                 }
3481                         
3482                 cfg->code_size = MAX (header->code_size * 5, 256);
3483                 cfg->start = cfg->code = g_malloc (cfg->code_size);
3484
3485                 /* fixme: make this arch independent */
3486                 mono_debug_last_breakpoint_address = cfg->code;
3487
3488                 if (match_debug_method (method) || mono_debug_insert_breakpoint)
3489                         x86_breakpoint (cfg->code);
3490                 else if (mono_debug_format != MONO_DEBUG_FORMAT_NONE)
3491                         x86_nop (cfg->code);
3492
3493                 if (mono_debug_insert_breakpoint > 0)
3494                         mono_debug_insert_breakpoint--;
3495
3496                 if (!(ji = arch_jit_compile_cfg (target_domain, cfg))) {
3497                         mono_profiler_method_end_jit (method, MONO_PROFILE_FAILED);
3498                         return NULL;
3499                 }
3500                 
3501                 addr = cfg->start;
3502
3503                 mono_jit_stats.allocated_code_size += cfg->code_size;
3504
3505                 code_size_ratio = cfg->code - cfg->start;
3506                 if (code_size_ratio > mono_jit_stats.biggest_method_size) {
3507                         mono_jit_stats.biggest_method_size = code_size_ratio;
3508                         mono_jit_stats.biggest_method = method;
3509                 }
3510                 code_size_ratio = (code_size_ratio * 100) / header->code_size;
3511                 if (code_size_ratio > mono_jit_stats.max_code_size_ratio) {
3512                         mono_jit_stats.max_code_size_ratio = code_size_ratio;
3513                         mono_jit_stats.max_ratio_method = method;
3514                 }
3515
3516                 
3517                 if (mono_jit_dump_asm) {
3518                         char *id = g_strdup_printf ("%s.%s_%s", method->klass->name_space,
3519                                                     method->klass->name, method->name);
3520                         mono_disassemble_code (cfg->start, cfg->code - cfg->start, id);
3521                         g_free (id);
3522                 }
3523                 if (mono_debug_format != MONO_DEBUG_FORMAT_NONE)
3524                         mono_debug_add_method (cfg);
3525
3526
3527                 mono_jit_stats.native_code_size += ji->code_size;
3528
3529                 if (header->num_clauses) {
3530                         int i, start_block, end_block;
3531
3532                         ji->num_clauses = header->num_clauses;
3533                         ji->clauses = mono_mempool_alloc0 (target_domain->mp, 
3534                                 sizeof (MonoJitExceptionInfo) * header->num_clauses);
3535
3536                         for (i = 0; i < header->num_clauses; i++) {
3537                                 MonoExceptionClause *ec = &header->clauses [i];
3538                                 MonoJitExceptionInfo *ei = &ji->clauses [i];
3539                         
3540                                 ei->flags = ec->flags;
3541                                 ei->token_or_filter = ec->token_or_filter;
3542
3543                                 g_assert (cfg->bcinfo [ec->try_offset].is_block_start);
3544                                 start_block = cfg->bcinfo [ec->try_offset].block_id;
3545                                 end_block = cfg->bcinfo [ec->try_offset + ec->try_len].block_id;
3546                                 g_assert (cfg->bcinfo [ec->try_offset + ec->try_len].is_block_start);
3547                                 
3548                                 ei->try_start = cfg->start + cfg->bblocks [start_block].addr;
3549                                 ei->try_end = cfg->start + cfg->bblocks [end_block].addr;
3550                                 
3551                                 g_assert (cfg->bcinfo [ec->handler_offset].is_block_start);
3552                                 start_block = cfg->bcinfo [ec->handler_offset].block_id;
3553                                 ei->handler_start = cfg->start + cfg->bblocks [start_block].addr;       
3554                                 
3555                                 //printf ("TEST %x %x %x\n", ei->try_start, ei->try_end, ei->handler_start);
3556                         }
3557                 }
3558                 
3559                 mono_jit_info_table_add (target_domain, ji);
3560
3561                 mono_regset_free (cfg->rs);
3562
3563                 mono_cfg_free (cfg);
3564
3565                 mono_profiler_method_end_jit (method, MONO_PROFILE_OK);
3566         }
3567
3568         if (mono_jit_trace_calls || mono_jit_dump_asm || mono_jit_dump_forest) {
3569                 printf ("END JIT compilation of %s.%s:%s %p %p\n", method->klass->name_space,
3570                         method->klass->name, method->name, method, addr);
3571         }
3572
3573         g_hash_table_insert (jit_code_hash, method, addr);
3574
3575         return addr;
3576 }
3577
3578 /* this function is never called */
3579 static void 
3580 ves_array_set (MonoArray *this, ...)
3581 {
3582         g_assert_not_reached ();
3583 }
3584
3585 /* this function is never called */
3586 static void 
3587 ves_array_get (MonoArray *this, ...)
3588 {
3589         g_assert_not_reached ();
3590 }
3591         
3592 /**
3593  * mono_jit_exec:
3594  * @assembly: reference to an assembly
3595  * @argc: argument count
3596  * @argv: argument vector
3597  *
3598  * Start execution of a program.
3599  */
3600 int 
3601 mono_jit_exec (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[])
3602 {
3603         MonoImage *image = assembly->image;
3604         MonoCLIImageInfo *iinfo;
3605         MonoMethod *method;
3606         MonoObject *exc;
3607         int rval;
3608
3609         iinfo = image->image_info;
3610         method = mono_get_method (image, iinfo->cli_cli_header.ch_entry_point, NULL);
3611
3612         rval = mono_runtime_run_main (method, argc, argv, &exc);
3613
3614         return rval;
3615 }
3616
3617 #ifdef PLATFORM_WIN32
3618 #define GET_CONTEXT \
3619         struct sigcontext *ctx = (struct sigcontext*)_dummy;
3620 #else
3621 #define GET_CONTEXT \
3622         void **_p = (void **)&_dummy; \
3623         struct sigcontext *ctx = (struct sigcontext *)++_p;
3624 #endif
3625
3626 static void
3627 sigfpe_signal_handler (int _dummy)
3628 {
3629         MonoException *exc;
3630         GET_CONTEXT
3631
3632         exc = mono_get_exception_divide_by_zero ();
3633         
3634         arch_handle_exception (ctx, exc);
3635
3636         g_error ("we should never reach this code");
3637 }
3638
3639 static void
3640 sigill_signal_handler (int _dummy)
3641 {
3642         MonoException *exc;
3643         GET_CONTEXT
3644
3645         exc = mono_get_exception_execution_engine ("SIGILL");
3646         
3647         arch_handle_exception (ctx, exc);
3648
3649         g_error ("we should never reach this code");
3650 }
3651
3652 static void
3653 sigsegv_signal_handler (int _dummy)
3654 {
3655         MonoException *exc;
3656         GET_CONTEXT
3657
3658         exc = mono_get_exception_null_reference ();
3659         
3660         arch_handle_exception (ctx, exc);
3661
3662         g_error ("we should never reach this code");
3663 }
3664
3665 /**
3666  * mono_thread_abort:
3667  * @obj: exception object
3668  *
3669  * abort the thread, print exception information and stack trace
3670  */
3671 static void
3672 mono_thread_abort (MonoObject *obj)
3673 {
3674         MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
3675         
3676         g_assert (obj);
3677
3678         if (jit_tls->env) {     
3679                 longjmp (*jit_tls->env, (int)obj);
3680         }
3681
3682         g_free (jit_tls);
3683
3684         ExitThread (-1);
3685 }
3686                 
3687 static void
3688 mono_thread_start_cb (gpointer stack_start)
3689 {
3690         MonoJitTlsData *jit_tls;
3691
3692         jit_tls = g_new0 (MonoJitTlsData, 1);
3693
3694         TlsSetValue (mono_jit_tls_id, jit_tls);
3695
3696         jit_tls->abort_func = mono_thread_abort;
3697         jit_tls->end_of_stack = stack_start;
3698 }
3699
3700 static CRITICAL_SECTION ms;
3701
3702 static void
3703 mono_runtime_install_handlers (void)
3704 {
3705 #ifndef PLATFORM_WIN32
3706         struct sigaction sa;
3707 #endif
3708
3709 #ifdef PLATFORM_WIN32
3710         win32_seh_init();
3711         win32_seh_set_handler(SIGFPE, sigfpe_signal_handler);
3712         win32_seh_set_handler(SIGILL, sigill_signal_handler);
3713         win32_seh_set_handler(SIGSEGV, sigsegv_signal_handler);
3714 #else /* !PLATFORM_WIN32 */
3715         /* catch SIGFPE */
3716         sa.sa_handler = sigfpe_signal_handler;
3717         sigemptyset (&sa.sa_mask);
3718         sa.sa_flags = 0;
3719         g_assert (syscall (SYS_sigaction, SIGFPE, &sa, NULL) != -1);
3720
3721         /* catch SIGILL */
3722         sa.sa_handler = sigill_signal_handler;
3723         sigemptyset (&sa.sa_mask);
3724         sa.sa_flags = 0;
3725         g_assert (syscall (SYS_sigaction, SIGILL, &sa, NULL) != -1);
3726
3727 #if 1
3728         /* catch SIGSEGV */
3729         sa.sa_handler = sigsegv_signal_handler;
3730         sigemptyset (&sa.sa_mask);
3731         sa.sa_flags = 0;
3732         g_assert (syscall (SYS_sigaction, SIGSEGV, &sa, NULL) != -1);
3733 #endif
3734 #endif /* PLATFORM_WIN32 */
3735 }
3736
3737 MonoDomain*
3738 mono_jit_init (char *file) {
3739         MonoDomain *domain;
3740
3741         mono_cpu_detect ();
3742
3743         mono_runtime_install_handlers ();
3744
3745         mono_init_icall ();
3746         mono_add_internal_call ("System.Array::Set", ves_array_set);
3747         mono_add_internal_call ("System.Array::Get", ves_array_get);
3748         mono_add_internal_call ("System.Array::Address", ves_array_element_address);
3749         mono_add_internal_call ("System.Diagnostics.StackFrame::get_frame_info", 
3750                                 ves_icall_get_frame_info);
3751
3752         metadata_section = &ms;
3753         InitializeCriticalSection (metadata_section);
3754
3755         mono_jit_tls_id = TlsAlloc ();
3756         mono_thread_start_cb (&file);
3757
3758         mono_install_trampoline (arch_create_jit_trampoline);
3759         mono_install_remoting_trampoline (arch_create_remoting_trampoline);
3760         mono_install_handler (arch_get_throw_exception ());
3761         mono_install_runtime_invoke (arch_runtime_invoke);
3762
3763         domain = mono_init (file);
3764         mono_runtime_init (domain, mono_thread_start_cb);
3765
3766         return domain;
3767 }
3768
3769 void
3770 mono_jit_cleanup (MonoDomain *domain)
3771 {
3772         mono_debug_cleanup ();
3773
3774 #ifdef PLATFORM_WIN32
3775         win32_seh_cleanup();
3776 #endif
3777
3778         mono_runtime_cleanup (domain);
3779
3780         mono_domain_unload (domain, TRUE);
3781
3782         if (mono_jit_stats.enabled) {
3783                 g_print ("Mono Jit statistics\n");
3784                 g_print ("Compiled methods:       %ld\n", mono_jit_stats.methods_compiled);
3785                 g_print ("Methods cache lookup:   %ld\n", mono_jit_stats.methods_lookups);
3786                 g_print ("Method trampolines:     %ld\n", mono_jit_stats.method_trampolines);
3787                 g_print ("Basic blocks:           %ld\n", mono_jit_stats.basic_blocks);
3788                 g_print ("Max basic blocks:       %ld\n", mono_jit_stats.max_basic_blocks);
3789                 g_print ("Allocated vars:         %ld\n", mono_jit_stats.allocate_var);
3790                 g_print ("Analyze stack repeat:   %ld\n", mono_jit_stats.analyze_stack_repeat);
3791                 g_print ("Compiled CIL code size: %ld\n", mono_jit_stats.cil_code_size);
3792                 g_print ("Native code size:       %ld\n", mono_jit_stats.native_code_size);
3793                 g_print ("Max code size ratio:    %.2f (%s::%s)\n", mono_jit_stats.max_code_size_ratio/100.0,
3794                                 mono_jit_stats.max_ratio_method->klass->name, mono_jit_stats.max_ratio_method->name);
3795                 g_print ("Biggest method:         %ld (%s::%s)\n", mono_jit_stats.biggest_method_size,
3796                                 mono_jit_stats.biggest_method->klass->name, mono_jit_stats.biggest_method->name);
3797                 g_print ("Code reallocs:          %ld\n", mono_jit_stats.code_reallocs);
3798                 g_print ("Allocated code size:    %ld\n", mono_jit_stats.allocated_code_size);
3799                 g_print ("Inlineable methods:     %ld\n", mono_jit_stats.inlineable_methods);
3800                 g_print ("Inlined methods:        %ld\n", mono_jit_stats.inlined_methods);
3801                 
3802                 g_print ("\nCreated object count:   %ld\n", mono_stats.new_object_count);
3803                 g_print ("Initialized classes:    %ld\n", mono_stats.initialized_class_count);
3804                 g_print ("Used classes:           %ld\n", mono_stats.used_class_count);
3805                 g_print ("Static data size:       %ld\n", mono_stats.class_static_data_size);
3806                 g_print ("VTable data size:       %ld\n", mono_stats.class_vtable_size);
3807         }
3808
3809         DeleteCriticalSection (metadata_section);
3810
3811 }
3812