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