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