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