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