Mon Nov 19 11:37:14 CET 2001 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 #include <glib.h>
12 #include <stdlib.h>
13 #include <stdarg.h>
14 #include <string.h>
15
16 #include <mono/metadata/assembly.h>
17 #include <mono/metadata/loader.h>
18 #include <mono/metadata/cil-coff.h>
19 #include <mono/metadata/tabledefs.h>
20 #include <mono/metadata/class.h>
21 #include <mono/metadata/object.h>
22 #include <mono/metadata/mono-endian.h>
23 #include <mono/metadata/tokentype.h>
24 #include <mono/arch/x86/x86-codegen.h>
25
26 #include "jit.h"
27 #include "regset.h"
28 #include "codegen.h"
29
30 /*
31  * Pull the list of opcodes
32  */
33 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
34         a = i,
35
36 enum {
37 #include "mono/cil/opcode.def"
38         LAST = 0xff
39 };
40 #undef OPDEF
41
42 #define OPDEF(a,b,c,d,e,f,g,h,i,j) b,
43 static char *opcode_names [] = {
44 #include "mono/cil/opcode.def"  
45 };
46 #undef OPDEF
47
48 #define SET_VARINFO(vi,t,k,o,s)  do { vi.type=t; vi.kind=k; vi.offset=o; vi.size=s; } while (0)
49
50 #define MAKE_CJUMP(name)                                                      \
51 case CEE_##name:                                                              \
52 case CEE_##name##_S: {                                                        \
53         gint32 target;                                                        \
54         int near_jump = *ip == CEE_##name##_S;                                \
55         ++ip;                                                                 \
56         sp -= 2;                                                              \
57         t1 = mono_ctree_new (mp, MB_TERM_##name, sp [0], sp [1]);             \
58         if (near_jump)                                                        \
59                 target = cli_addr + 2 + (signed char) *ip;                    \
60         else                                                                  \
61                 target = cli_addr + 5 + (gint32) read32 (ip);                 \
62         g_assert (target >= 0 && target <= header->code_size);                \
63         g_assert (bcinfo [target].is_block_start);                            \
64         tbb = &cfg->bblocks [bcinfo [target].block_id];                       \
65         create_outstack (cfg, bb, stack, sp - stack);                         \
66         mark_reached (cfg, tbb, bb->outstack, bb->outdepth);                  \
67         t1->data.p = tbb;                                                     \
68         ADD_TREE (t1);                                                        \
69         ip += near_jump ? 1: 4;                                               \
70         break;                                                                \
71 }
72
73 #define MAKE_BI_ALU(name)                                                     \
74 case CEE_##name: {                                                            \
75         ++ip;                                                                 \
76         sp -= 2;                                                              \
77         t1 = mono_ctree_new (mp, MB_TERM_##name, sp [0], sp [1]);             \
78         g_assert (sp [0]->svt == sp [1]->svt);                                \
79         PUSH_TREE (t1, sp [0]->svt);                                          \
80         break;                                                                \
81 }
82
83 #define MAKE_LDIND(name, op, svt)                                             \
84 case CEE_##name: {                                                            \
85         ++ip;                                                                 \
86         sp--;                                                                 \
87         t1 = mono_ctree_new (mp, op, *sp, NULL);                              \
88         PUSH_TREE (t1, svt);                                                  \
89         break;                                                                \
90 }
91         
92 #define MAKE_LDELEM(name, op, svt, s)                                         \
93 case CEE_##name: {                                                            \
94         ++ip;                                                                 \
95         sp -= 2;                                                              \
96         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);                      \
97         t1->data.i = s;                                                       \
98         t1 = mono_ctree_new (mp, MB_TERM_MUL, sp [1], t1);                    \
99         t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);                      \
100         t2->data.i = G_STRUCT_OFFSET (MonoArray, vector);                     \
101         t2 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t2);                    \
102         t1 = mono_ctree_new (mp, MB_TERM_ADD, t1, t2);                        \
103         t1 = mono_ctree_new (mp, op, t1, NULL);                               \
104         PUSH_TREE (t1, svt);                                                  \
105         break;                                                                \
106 }
107         
108 #define MAKE_STIND(name, op)                                                  \
109 case CEE_##name: {                                                            \
110         ++ip;                                                                 \
111         sp -= 2;                                                              \
112         t1 = mono_ctree_new (mp, op, sp [0], sp [1]);                         \
113         ADD_TREE (t1);                                                        \
114         break;                                                                \
115 }
116
117 #define MAKE_STELEM(name, op, s)                                              \
118 case CEE_##name: {                                                            \
119         ++ip;                                                                 \
120         sp -= 3;                                                              \
121         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);                      \
122         t1->data.i = s;                                                       \
123         t1 = mono_ctree_new (mp, MB_TERM_MUL, sp [1], t1);                    \
124         t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);                      \
125         t2->data.i = G_STRUCT_OFFSET (MonoArray, vector);                     \
126         t2 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t2);                    \
127         t1 = mono_ctree_new (mp, MB_TERM_ADD, t1, t2);                        \
128         t1 = mono_ctree_new (mp, op, t1, sp [2]);                             \
129         ADD_TREE (t1);                                                        \
130         break;                                                                \
131 }
132         
133 /* Whether to dump the assembly code after genreating it */
134 gboolean mono_jit_dump_asm = FALSE;
135
136 /* Whether to dump the forest */
137 gboolean mono_jit_dump_forest = FALSE;
138
139 /* Whether to print function call traces */
140 gboolean mono_jit_trace_calls = FALSE;
141
142 /* 
143  * We sometimes need static data, for example the forest generator need it to
144  * store constants or class data.
145  */
146 inline static gpointer
147 mono_alloc_static (int size)
148 {
149         return g_malloc (size);
150
151 inline static gpointer
152 mono_alloc_static0 (int size)
153 {
154         return g_malloc0 (size);
155
156
157
158 typedef void (*MonoCCtor) (void);
159
160 /**
161  * mono_jit_init_class:
162  * @klass: the class to initialise
163  *
164  * Initialise the class @klass by calling the class
165  * constructor.
166  */
167 static void
168 mono_jit_init_class (MonoClass *klass)
169 {
170         MonoCCtor cctor;
171         MonoMethod *method;
172         int i;
173
174         if (!klass->metadata_inited)
175                 mono_class_metadata_init (klass);
176
177         if (klass->inited)
178                 return;
179
180         if (klass->parent && !klass->parent->inited)
181                 mono_jit_init_class (klass->parent);
182         
183         klass->inited = 1;
184
185         for (i = 0; i < klass->method.count; ++i) {
186                 method = klass->methods [i];
187                 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && 
188                     (strcmp (".cctor", method->name) == 0)) {
189         
190                         cctor = arch_compile_method (method);
191                         cctor ();
192                         return;
193                 }
194         }
195         /* No class constructor found */
196 }
197
198 static int
199 map_store_svt_type (int svt)
200 {
201         switch (svt) {
202         case VAL_I32:
203         case VAL_POINTER:
204                 return MB_TERM_STIND_I4;
205         case VAL_I64:
206                 return MB_TERM_STIND_I8;
207         case VAL_DOUBLE:
208                 return MB_TERM_STIND_R8;
209         default:
210                 g_assert_not_reached ();
211         }
212
213         return 0;
214 }
215
216 static int
217 map_stvalue_type (MonoClass *class)
218 {
219         int size;
220
221         g_assert (class->valuetype);
222
223         if (!class->inited)
224                 mono_jit_init_class (class);
225
226         size =  class->instance_size - sizeof (MonoObject);
227
228         switch (size) {
229         case 4:
230                 return MB_TERM_STIND_I4;
231         case 2:
232                 return MB_TERM_STIND_I2;
233         case 1:
234                 return MB_TERM_STIND_I1;
235         }
236         return MB_TERM_STIND_OBJ;
237 }
238
239 /**
240  * map_stind_type:
241  * @type: the type to map
242  *
243  * Translates the MonoType @type into the corresponding store opcode 
244  * for the code generator.
245  */
246 static int
247 map_stind_type (MonoType *type)
248 {
249         if (type->byref) 
250                 return MB_TERM_STIND_I4;
251
252         switch (type->type) {
253         case MONO_TYPE_I1:
254         case MONO_TYPE_U1:
255         case MONO_TYPE_BOOLEAN:
256                 return MB_TERM_STIND_I1;        
257         case MONO_TYPE_I2:
258         case MONO_TYPE_U2:
259         case MONO_TYPE_CHAR:
260                 return MB_TERM_STIND_I2;        
261         case MONO_TYPE_I:
262         case MONO_TYPE_I4:
263         case MONO_TYPE_U4:
264         case MONO_TYPE_CLASS:
265         case MONO_TYPE_OBJECT:
266         case MONO_TYPE_STRING:
267         case MONO_TYPE_PTR:
268         case MONO_TYPE_SZARRAY:
269         case MONO_TYPE_ARRAY:    
270                 return MB_TERM_STIND_I4;
271         case MONO_TYPE_I8:
272         case MONO_TYPE_U8:
273                 return MB_TERM_STIND_I8;
274         case MONO_TYPE_R4:
275                 return MB_TERM_STIND_R4;
276         case MONO_TYPE_R8:
277                 return MB_TERM_STIND_R8;
278         case MONO_TYPE_VALUETYPE: 
279                 return map_stvalue_type (type->data.klass);
280         default:
281                 g_warning ("unknown type %02x", type->type);
282                 g_assert_not_reached ();
283         }
284
285         g_assert_not_reached ();
286         return -1;
287 }
288
289 /**
290  * map_ldind_type:
291  * @type: the type to map
292  *
293  * Translates the MonoType @type into the corresponding load opcode 
294  * for the code generator.
295  */
296 static int
297 map_ldind_type (MonoType *type, MonoValueType *svt)
298 {
299         if (type->byref) {
300                 *svt = VAL_POINTER;
301                 return MB_TERM_LDIND_I4;
302         }
303
304         switch (type->type) {
305         case MONO_TYPE_I1:
306                 *svt = VAL_I32;
307                 return MB_TERM_LDIND_I1;
308         case MONO_TYPE_U1:
309         case MONO_TYPE_BOOLEAN:
310                 *svt = VAL_I32;
311                 return MB_TERM_LDIND_U1;
312         case MONO_TYPE_I2:
313                 *svt = VAL_I32;
314                 return MB_TERM_LDIND_I2;
315         case MONO_TYPE_U2:
316         case MONO_TYPE_CHAR:
317                 *svt = VAL_I32;
318                 return MB_TERM_LDIND_U2;
319         case MONO_TYPE_I:
320         case MONO_TYPE_I4:
321                 *svt = VAL_I32;
322                 return MB_TERM_LDIND_I4;
323         case MONO_TYPE_U4:
324                 *svt = VAL_I32;
325                 return MB_TERM_LDIND_U4;
326         case MONO_TYPE_CLASS:
327         case MONO_TYPE_OBJECT:
328         case MONO_TYPE_STRING:
329         case MONO_TYPE_PTR:
330         case MONO_TYPE_SZARRAY:
331         case MONO_TYPE_ARRAY:    
332                 *svt = VAL_POINTER;
333                 return MB_TERM_LDIND_U4;
334         case MONO_TYPE_I8:
335         case MONO_TYPE_U8:
336                 *svt = VAL_I64;
337                 return MB_TERM_LDIND_I8;
338         case MONO_TYPE_R4:
339                 *svt = VAL_DOUBLE;
340                 return MB_TERM_LDIND_R4;
341         case MONO_TYPE_R8:
342                 *svt = VAL_DOUBLE;
343                 return MB_TERM_LDIND_R8;
344         case MONO_TYPE_VALUETYPE: {
345                 int size, align;
346                 size = mono_type_size (type, &align);
347
348                 switch (size) {
349                 case 4:
350                         *svt = VAL_I32;
351                         return MB_TERM_LDIND_U4;
352                 case 2:
353                         *svt = VAL_I32;
354                         return MB_TERM_LDIND_U2;
355                 case 1:
356                         *svt = VAL_I32;
357                         return MB_TERM_LDIND_U1;
358                 default:
359                         g_assert_not_reached ();
360                 }
361         }
362         default:
363                 g_warning ("unknown type %02x", type->type);
364                 g_assert_not_reached ();
365         }
366
367         g_assert_not_reached ();
368         return -1;
369 }
370
371 /**
372  * map_call_type:
373  * @type: the type to map
374  *
375  * Translates the MonoType @type into the corresponding call opcode 
376  * for the code generator.
377  */
378 static int
379 map_call_type (MonoType *type, MonoValueType *svt)
380 {
381         switch (type->type) {
382         case MONO_TYPE_VOID:
383                 *svt = VAL_UNKNOWN;
384                 return MB_TERM_CALL_VOID;
385         case MONO_TYPE_I1:
386         case MONO_TYPE_U1:
387         case MONO_TYPE_BOOLEAN:
388         case MONO_TYPE_I2:
389         case MONO_TYPE_U2:
390         case MONO_TYPE_CHAR:
391         case MONO_TYPE_I:
392         case MONO_TYPE_I4:
393         case MONO_TYPE_U4:
394                 *svt = VAL_I32;
395                 return MB_TERM_CALL_I4;
396         case MONO_TYPE_VALUETYPE:
397                 *svt = VAL_I32;
398                 return MB_TERM_CALL_VOID;
399         case MONO_TYPE_CLASS:
400         case MONO_TYPE_OBJECT:
401         case MONO_TYPE_STRING:
402         case MONO_TYPE_PTR:
403         case MONO_TYPE_SZARRAY: 
404                 *svt = VAL_POINTER;
405                 return MB_TERM_CALL_I4;
406         case MONO_TYPE_I8:
407         case MONO_TYPE_U8:
408                 *svt = VAL_I64;
409                 return MB_TERM_CALL_I8;
410         case MONO_TYPE_R4:
411         case MONO_TYPE_R8:
412                 *svt = VAL_DOUBLE;
413                 return MB_TERM_CALL_R8;
414         default:
415                 g_warning ("unknown type %02x", type->type);
416                 g_assert_not_reached ();
417         }
418
419         g_assert_not_reached ();
420         return -1;
421 }
422
423 /*
424  * prints the tree to stdout
425  */
426 void
427 mono_print_ctree (MBTree *tree)
428 {
429         int arity;
430
431         if (!tree)
432                 return;
433
434         arity = (tree->left != NULL) + (tree->right != NULL);
435
436         if (arity)
437                 printf (" (%s", mono_burg_term_string [tree->op]);
438         else 
439                 printf (" %s", mono_burg_term_string [tree->op]);
440
441         switch (tree->op) {
442         case MB_TERM_ADDR_L:
443                 printf ("[%d]", tree->data.i);
444                 break;
445         }
446
447         g_assert (!(tree->right && !tree->left));
448
449         mono_print_ctree (tree->left);
450         mono_print_ctree (tree->right);
451
452         if (arity)
453                 printf (")");
454 }
455
456 /*
457  * prints the whole forest to stdout
458  */
459 void
460 mono_print_forest (GPtrArray *forest)
461 {
462         const int top = forest->len;
463         int i;
464
465         for (i = 0; i < top; i++) {
466                 MBTree *t = (MBTree *) g_ptr_array_index (forest, i);
467                 printf ("       ");
468                 mono_print_ctree (t);
469                 printf ("\n");
470         }
471
472 }
473
474 /**
475  * mono_disassemble_code:
476  * @code: a pointer to the code
477  * @size: the code size in bytes
478  *
479  * Disassemble to code to stdout.
480  */
481 void
482 mono_disassemble_code (guint8 *code, int size)
483 {
484         int i;
485         FILE *ofd;
486
487         if (!(ofd = fopen ("/tmp/test.s", "w")))
488                 g_assert_not_reached ();
489
490         for (i = 0; i < size; ++i) 
491                 fprintf (ofd, ".byte %d\n", (unsigned int) code [i]);
492
493         fclose (ofd);
494
495         system ("as /tmp/test.s -o /tmp/test.o;objdump -d /tmp/test.o"); 
496 }
497
498 static int
499 arch_allocate_var (MonoFlowGraph *cfg, int size, int align, MonoValueKind kind, MonoValueType type)
500 {
501         MonoVarInfo vi;
502
503         switch (kind) {
504         case MONO_TEMPVAR:
505         case MONO_LOCALVAR: {
506                 cfg->locals_size += align - 1;
507                 cfg->locals_size &= ~(align - 1);
508                 cfg->locals_size += size;
509
510                 SET_VARINFO (vi, type, kind, - cfg->locals_size, size);
511                 g_array_append_val (cfg->varinfo, vi);
512                 break;
513         }
514         case MONO_ARGVAR: {
515                 SET_VARINFO (vi, type, kind, cfg->args_size + 8, size);
516                 g_array_append_val (cfg->varinfo, vi);
517
518                 cfg->args_size += align - 1;
519                 cfg->args_size &= ~(align - 1);
520                 cfg->args_size += size;
521                 break;
522         }
523         default:
524                 g_assert_not_reached ();
525         }
526
527         return cfg->varinfo->len - 1;
528 }
529
530 inline static void
531 mono_get_val_sizes (MonoValueType type, int *size, int *align) 
532
533         switch (type) {
534         case VAL_I32:
535                 *size = *align = sizeof (gint32);
536                 break;
537         case VAL_I64:
538                 *size = *align = sizeof (gint64);
539                 break;
540         case VAL_POINTER:
541                 *size = *align = sizeof (gpointer);
542                 break;
543         case VAL_DOUBLE:
544                 *size = *align = sizeof (double);
545                 break;
546         default:
547                 g_assert_not_reached ();
548         }
549 }
550
551 static int
552 mono_allocate_intvar (MonoFlowGraph *cfg, int slot, MonoValueType type)
553 {
554         int size, align, vnum;
555         
556         g_assert (type != VAL_UNKNOWN);
557
558         if ((vnum = cfg->intvars [type - 1 + slot * VAL_DOUBLE]))
559                 return vnum;
560
561         mono_get_val_sizes (type, &size, &align);
562
563         return cfg->intvars[type - 1 + slot * VAL_DOUBLE] = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, type);
564 }
565
566 /**
567  * ctree_create_load:
568  * @cfg: pointer to the control flow graph
569  * @type: the type of the value to load
570  * @addr: the address of the value
571  *
572  * Creates a tree to load the value at address @addr.
573  */
574 inline static MBTree *
575 ctree_create_load (MonoFlowGraph *cfg, MonoType *type, MBTree *addr, MonoValueType *svt)
576 {
577         MonoMemPool *mp = cfg->mp;
578         int ldind, size, align, vnum;
579         MBTree *t;
580
581         if (type->type == MONO_TYPE_VALUETYPE) {
582                 size = mono_type_size (type, &align);
583
584                 if (size > 4 || size == 3) {
585                 
586                         vnum = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, VAL_UNKNOWN);
587                         t = mono_ctree_new (mp, MB_TERM_LDIND_OBJ, addr, NULL);
588                         t->data.i = vnum;
589                         return t;
590                 }
591         }
592
593         ldind = map_ldind_type (type, svt);
594         t = mono_ctree_new (mp, ldind, addr, NULL);
595
596         return t;
597 }
598
599 /**
600  * ctree_create_store:
601  * @mp: pointer to a memory pool
602  * @addr_type: address type (MB_TERM_ADDR_L or MB_TERM_ADDR_G)
603  * @s: the value (tree) to store
604  * @type: the type of the value
605  * @addr: the address of the value
606  *
607  * Creates a tree to store the value @s at address @addr.
608  */
609 inline static MBTree *
610 ctree_create_store (MonoMemPool *mp, int addr_type, MBTree *s, MonoType *type, gpointer addr)
611 {
612         int stind = map_stind_type (type);
613         MBTree *t;
614
615         t = mono_ctree_new_leaf (mp, addr_type);
616         t->data.p = addr;
617         t = mono_ctree_new (mp, stind, t, s);
618
619         return t;
620 }
621
622 inline static MBTree *
623 ctree_dup_address (MonoMemPool *mp, MBTree *s)
624 {
625         MBTree *t;
626
627         switch (s->op) {
628
629         case MB_TERM_ADDR_L:
630         case MB_TERM_ADDR_G:
631                 t = mono_ctree_new_leaf (mp, s->op);
632                 t->data.i = s->data.i;
633                 t->svt = VAL_POINTER;
634                 return t;
635         default:
636                 g_warning ("unknown tree opcode %d", s->op);
637                 g_assert_not_reached ();
638         }
639
640         return NULL;
641 }
642
643 /**
644  * Create a duplicate of the value of a tree. This is
645  * easy for trees starting with LDIND/STIND, since the
646  * duplicate is simple a LDIND tree with the same address.
647  * For other trees we have to split the tree into one tree
648  * storing the value to a new temporary variable, and 
649  * another tree which loads that value back. We can then
650  * duplicate the second tree.
651  */
652 static MBTree *
653 ctree_create_dup (MonoMemPool *mp, MBTree *s)
654 {
655         MBTree *t;
656         
657         switch (s->op) {
658         case MB_TERM_STIND_I1:
659         case MB_TERM_LDIND_I1:
660                 t = ctree_dup_address (mp, s->left);
661                 t = mono_ctree_new (mp, MB_TERM_LDIND_I1, t, NULL);
662                 t->svt = VAL_I32;
663                 break;
664         case MB_TERM_STIND_I2:
665         case MB_TERM_LDIND_I2:
666                 t = ctree_dup_address (mp, s->left);
667                 t = mono_ctree_new (mp, MB_TERM_LDIND_I2, t, NULL);
668                 t->svt = VAL_I32;
669                 break;
670         case MB_TERM_STIND_I4:
671         case MB_TERM_LDIND_I4:
672                 t = ctree_dup_address (mp, s->left);
673                 t = mono_ctree_new (mp, MB_TERM_LDIND_I4, t, NULL);
674                 t->svt = VAL_I32;
675                 break;
676         case MB_TERM_LDIND_U4:
677                 t = ctree_dup_address (mp, s->left);
678                 t = mono_ctree_new (mp, MB_TERM_LDIND_U4, t, NULL);
679                 t->svt = VAL_I32;
680                 break;
681         case MB_TERM_STIND_I8:
682         case MB_TERM_LDIND_I8:
683                 t = ctree_dup_address (mp, s->left);
684                 t = mono_ctree_new (mp, MB_TERM_LDIND_I8, t, NULL);
685                 t->svt = VAL_I64;
686                 break;
687         case MB_TERM_STIND_R4:
688         case MB_TERM_LDIND_R4:
689                 t = ctree_dup_address (mp, s->left);
690                 t = mono_ctree_new (mp, MB_TERM_LDIND_R4, t, NULL);
691                 t->svt = VAL_DOUBLE;
692                 break;
693         case MB_TERM_STIND_R8:
694         case MB_TERM_LDIND_R8:
695                 t = ctree_dup_address (mp, s->left);
696                 t = mono_ctree_new (mp, MB_TERM_LDIND_R8, t, NULL);
697                 t->svt = VAL_DOUBLE;
698                 break;
699         default:
700                 g_warning ("unknown op \"%s\"", mono_burg_term_string [s->op]);
701                 g_assert_not_reached ();
702         }
703
704         return t;
705 }
706
707 static MBTree *
708 mono_store_tree (MonoFlowGraph *cfg, int slot, MBTree *s, MBTree **dup)
709 {
710         MonoMemPool *mp = cfg->mp;
711         MBTree *t;
712         int vnum;
713
714         switch (s->op) {
715         case MB_TERM_STIND_I1:
716         case MB_TERM_LDIND_I1:
717         case MB_TERM_STIND_I2:
718         case MB_TERM_LDIND_I2:
719         case MB_TERM_STIND_I4:
720         case MB_TERM_LDIND_I4:
721         case MB_TERM_STIND_I8:
722         case MB_TERM_LDIND_I8:
723         case MB_TERM_STIND_R4:
724         case MB_TERM_LDIND_R4:
725         case MB_TERM_STIND_R8:
726         case MB_TERM_LDIND_R8: {
727                 if (slot >= 0) {
728                         vnum = mono_allocate_intvar (cfg, slot, s->svt);
729
730                         if (s->left->op == MB_TERM_ADDR_L && s->left->data.i == vnum) {
731                                 if (dup)
732                                         *dup = ctree_create_dup (mp, s);
733                                 return NULL;
734                         }
735                         // fall through
736                 } else {
737                         if (dup)
738                                 *dup = ctree_create_dup (mp, s);
739                         return NULL;
740                 }
741         }                       
742         default: {
743                         g_assert (s->svt != VAL_UNKNOWN);
744
745                         if (slot >= 0) {
746                                 vnum = mono_allocate_intvar (cfg, slot, s->svt);
747                         } else {
748                                 int size, align;
749                                 mono_get_val_sizes (s->svt, &size, &align);
750                                 vnum = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, s->svt);
751                         }
752
753                         t = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
754                         t->data.i = vnum;
755                        
756                         t = mono_ctree_new (mp, map_store_svt_type (s->svt), t, s);
757                         t->svt = s->svt;
758                 }
759         }
760
761         if (dup) 
762                 mono_store_tree (cfg, -1, t, dup);
763
764         return t;
765 }
766
767 MonoFlowGraph *
768 mono_cfg_new (MonoMethod *method, MonoMemPool *mp)
769 {
770         MonoVarInfo vi;
771         MonoFlowGraph *cfg;
772
773         cfg = mono_mempool_alloc0 (mp, sizeof (MonoFlowGraph));
774
775         cfg->method = method;
776         cfg->mp = mp;
777
778         cfg->varinfo = g_array_new (FALSE, TRUE, sizeof (MonoVarInfo));
779         
780         SET_VARINFO (vi, 0, 0, 0, 0);
781         g_array_append_val (cfg->varinfo, vi); /* add invalid value at position 0 */
782
783         cfg->intvars = mono_mempool_alloc0 (mp, sizeof (guint16) * VAL_DOUBLE * 
784                                             ((MonoMethodNormal *)method)->header->max_stack);
785         return cfg;
786 }
787
788 void
789 mono_cfg_free (MonoFlowGraph *cfg)
790 {
791         int i;
792
793         for (i = 0; i < cfg->block_count; i++) {
794                 g_ptr_array_free (cfg->bblocks [i].forest, TRUE);
795         }
796
797         g_array_free (cfg->varinfo, TRUE);
798 }
799
800 #define CREATE_BLOCK(t) {if (!bcinfo [t].is_block_start) {block_count++;bcinfo [t].is_block_start = 1; }}
801
802 void
803 mono_analyze_flow (MonoFlowGraph *cfg)
804 {
805         MonoMethod *method = cfg->method;
806         MonoMemPool *mp = cfg->mp;
807         register const unsigned char *ip, *end;
808         MonoMethodHeader *header;
809         MonoBytecodeInfo *bcinfo;
810         MonoBBlock *bblocks, *bb;
811         gboolean block_end;
812         int i, block_count;
813
814         header = ((MonoMethodNormal *)method)->header;
815
816         bcinfo = mono_mempool_alloc0 (mp, header->code_size * sizeof (MonoBytecodeInfo));
817         bcinfo [0].is_block_start = 1;
818         block_count = 1;
819         block_end = FALSE;
820
821         ip = header->code;
822         end = ip + header->code_size;
823
824         /* fixme: add block boundaries for exceptions */
825
826         while (ip < end) {
827                 guint32 cli_addr = ip - header->code;
828
829                 //printf ("IL%04x OPCODE %s\n", cli_addr, opcode_names [*ip]);
830                 
831                 if (block_end) {
832                         CREATE_BLOCK (cli_addr);
833                         block_end = FALSE;
834                 }
835
836                 switch (*ip) {
837
838                 case CEE_THROW:
839                         ip++;
840                         block_end = 1;
841                         break;
842                 case CEE_NOP: 
843                 case CEE_BREAK:
844                 case CEE_LDC_I4_M1:
845                 case CEE_LDC_I4_0:
846                 case CEE_LDC_I4_1:
847                 case CEE_LDC_I4_2:
848                 case CEE_LDC_I4_3:
849                 case CEE_LDC_I4_4:
850                 case CEE_LDC_I4_5:
851                 case CEE_LDC_I4_6:
852                 case CEE_LDC_I4_7:
853                 case CEE_LDC_I4_8:
854                 case CEE_LDNULL:
855                 case CEE_LDLOC_0:
856                 case CEE_LDLOC_1:
857                 case CEE_LDLOC_2:
858                 case CEE_LDLOC_3:
859                 case CEE_STLOC_0:
860                 case CEE_STLOC_1:
861                 case CEE_STLOC_2:
862                 case CEE_STLOC_3: 
863                 case CEE_LDARG_0:
864                 case CEE_LDARG_1:
865                 case CEE_LDARG_2:
866                 case CEE_LDARG_3:
867                 case CEE_NEG:
868                 case CEE_NOT:
869                 case CEE_DUP:
870                 case CEE_POP:
871                 case CEE_ADD:
872                 case CEE_SUB:
873                 case CEE_AND:
874                 case CEE_OR:
875                 case CEE_XOR:
876                 case CEE_SHL:
877                 case CEE_SHR:
878                 case CEE_SHR_UN:
879                 case CEE_MUL:
880                 case CEE_DIV:
881                 case CEE_DIV_UN:
882                 case CEE_REM:
883                 case CEE_REM_UN:
884                 case CEE_LDIND_I1:
885                 case CEE_LDIND_U1:
886                 case CEE_LDIND_I2:
887                 case CEE_LDIND_U2:
888                 case CEE_LDIND_I:
889                 case CEE_LDIND_I4:
890                 case CEE_LDIND_REF:
891                 case CEE_LDIND_U4:
892                 case CEE_LDIND_I8:
893                 case CEE_LDIND_R4:
894                 case CEE_LDIND_R8:
895                 case CEE_STIND_I1:
896                 case CEE_STIND_I2:
897                 case CEE_STIND_I:
898                 case CEE_STIND_I4:
899                 case CEE_STIND_I8:
900                 case CEE_STIND_R4:
901                 case CEE_STIND_R8:
902                 case CEE_STIND_REF:
903                 case CEE_STELEM_I:
904                 case CEE_STELEM_I1:
905                 case CEE_STELEM_I2:
906                 case CEE_STELEM_I4:
907                 case CEE_STELEM_I8:
908                 case CEE_STELEM_R4:
909                 case CEE_STELEM_R8:
910                 case CEE_STELEM_REF:
911                 case CEE_LDLEN:
912                 case CEE_LDELEM_I1:
913                 case CEE_LDELEM_U1:
914                 case CEE_LDELEM_I2:
915                 case CEE_LDELEM_U2:
916                 case CEE_LDELEM_I4:
917                 case CEE_LDELEM_U4:
918                 case CEE_LDELEM_I8:
919                 case CEE_LDELEM_I:
920                 case CEE_LDELEM_R4:
921                 case CEE_LDELEM_R8:
922                 case CEE_LDELEM_REF:
923                 case CEE_CONV_OVF_I_UN:
924                 case CEE_CONV_OVF_U_UN:
925                 case CEE_CONV_OVF_I1_UN:
926                 case CEE_CONV_OVF_U1_UN:
927                 case CEE_CONV_OVF_I2_UN:
928                 case CEE_CONV_OVF_U2_UN:
929                 case CEE_CONV_OVF_I4_UN:
930                 case CEE_CONV_OVF_U4_UN:
931                 case CEE_CONV_OVF_I8_UN:
932                 case CEE_CONV_OVF_U8_UN:
933                 case CEE_CONV_OVF_I:
934                 case CEE_CONV_OVF_U:
935                 case CEE_CONV_OVF_I1:
936                 case CEE_CONV_OVF_U1:
937                 case CEE_CONV_OVF_I2:
938                 case CEE_CONV_OVF_U2:
939                 case CEE_CONV_OVF_I4:
940                 case CEE_CONV_OVF_U4:
941                 case CEE_CONV_OVF_I8:
942                 case CEE_CONV_OVF_U8:
943                 case CEE_CONV_I1:
944                 case CEE_CONV_U1:
945                 case CEE_CONV_I2:
946                 case CEE_CONV_U2:
947                 case CEE_CONV_I:
948                 case CEE_CONV_U:
949                 case CEE_CONV_I4:
950                 case CEE_CONV_U4:
951                 case CEE_CONV_I8:
952                 case CEE_CONV_U8:
953                 case CEE_CONV_R4:
954                 case CEE_CONV_R8:
955                         ip++;
956                         break;
957                 case CEE_RET:
958                         ip++;
959                         block_end = 1;
960                         break;
961                 case CEE_BOX:
962                 case CEE_UNBOX:
963                 case CEE_LDOBJ:
964                 case CEE_LDSTR:
965                 case CEE_LDSFLD:
966                 case CEE_LDSFLDA:
967                 case CEE_LDFLD:
968                 case CEE_LDFLDA:
969                 case CEE_STSFLD: 
970                 case CEE_STFLD:
971                 case CEE_LDELEMA:
972                 case CEE_NEWOBJ:
973                 case CEE_CPOBJ:
974                 case CEE_NEWARR:
975                 case CEE_LDTOKEN:
976                 case CEE_CALL:
977                 case CEE_CALLVIRT:
978                 case CEE_ISINST:
979                 case CEE_CASTCLASS:
980                 case CEE_LDC_I4:
981                 case CEE_LDC_R4:
982                         ip += 5;
983                         break;
984                 case CEE_BR:
985                 case CEE_LEAVE:
986                 case CEE_BRTRUE:
987                 case CEE_BRFALSE:
988                 case CEE_BGT:
989                 case CEE_BGT_UN:
990                 case CEE_BLT:
991                 case CEE_BLT_UN:
992                 case CEE_BNE_UN:
993                 case CEE_BEQ:
994                 case CEE_BGE:
995                 case CEE_BGE_UN:
996                 case CEE_BLE:
997                 case CEE_BLE_UN: {
998                         gint32 offset;
999                         ip++;
1000                         offset = read32 (ip);
1001                         ip += 4;
1002                         CREATE_BLOCK (cli_addr + 5 + offset);
1003                         block_end = 1;
1004                         break;
1005                 }
1006                 case CEE_LDC_I8:
1007                 case CEE_LDC_R8:
1008                         ip += 9;
1009                         break;
1010                 case CEE_LDC_I4_S:
1011                 case CEE_LDLOC_S:
1012                 case CEE_LDLOCA_S:
1013                 case CEE_STLOC_S:
1014                 case CEE_LDARG_S: 
1015                 case CEE_LDARGA_S: 
1016                 case CEE_STARG_S:
1017                         ip += 2;
1018                         break;
1019                 case CEE_BR_S:
1020                 case CEE_LEAVE_S:
1021                 case CEE_BRTRUE_S:
1022                 case CEE_BRFALSE_S:
1023                 case CEE_BGT_S:
1024                 case CEE_BGT_UN_S:
1025                 case CEE_BLT_S:
1026                 case CEE_BLT_UN_S:
1027                 case CEE_BNE_UN_S:
1028                 case CEE_BEQ_S:
1029                 case CEE_BGE_S:
1030                 case CEE_BGE_UN_S:
1031                 case CEE_BLE_S:
1032                 case CEE_BLE_UN_S: {
1033                         gint32 offset;
1034                         ip++;
1035                         offset = (signed char)*ip;
1036                         ip++;
1037                         CREATE_BLOCK (cli_addr + 2 + offset);
1038                         block_end = 1;
1039                         break;
1040                 }
1041                 case CEE_SWITCH: {
1042                         gint32 i, st, target, n;
1043                         ++ip;
1044                         n = read32 (ip);
1045                         ip += 4;
1046                         st = cli_addr + 5 + 4 * n;
1047                         CREATE_BLOCK (st);
1048
1049                         for (i = 0; i < n; i++) {
1050                                 target = read32 (ip) + st;
1051                                 ip += 4;
1052                                 CREATE_BLOCK (target);                  
1053                         }
1054                         break;
1055                 }
1056                 case 0xFE: {
1057                         ++ip;                   
1058                         switch (*ip) {
1059                                 
1060                         case CEE_CEQ:
1061                         case CEE_CLT:
1062                                 ip++;
1063                                 break;
1064                         case CEE_LDARG:
1065                         case CEE_INITOBJ:
1066                                 ip +=5;
1067                                 break;
1068                         default:
1069                                 g_error ("Unimplemented opcode at IL_%04x "
1070                                          "0xFE %02x", ip - header->code, *ip);
1071                         }
1072                         break;
1073                 }
1074
1075                 default:
1076                         g_warning ("unknown instruction `%s' at IL_%04X", 
1077                                    opcode_names [*ip], ip - header->code);
1078                         g_assert_not_reached ();
1079                 }
1080         }
1081
1082
1083         g_assert (block_count);
1084
1085         bb = bblocks  = mono_mempool_alloc0 (mp, sizeof (MonoBBlock) * block_count);
1086
1087         block_count = 0;
1088         bblocks [0].reached = 1;
1089
1090         for (i = 0; i < header->code_size; i++) {
1091                 if (bcinfo [i].is_block_start) {
1092                         bb->cli_addr = i;
1093                         if (block_count)
1094                                 bb [-1].length = i - bb [-1].cli_addr; 
1095                         bcinfo [i].block_id = block_count;
1096                         bb++;
1097                         block_count++;
1098                 }
1099         }
1100         bb [-1].length = header->code_size - bb [-1].cli_addr; 
1101
1102         cfg->bcinfo = bcinfo;
1103         cfg->bblocks = bblocks;
1104         cfg->block_count = block_count;
1105 }
1106
1107 /**
1108  * ves_array_element_address:
1109  * @this: a pointer to the array object
1110  *
1111  * Returns: the address of an array element.
1112  */
1113 static gpointer 
1114 ves_array_element_address (MonoArray *this, ...)
1115 {
1116         MonoClass *class;
1117         va_list ap;
1118         int i, ind, esize;
1119         gpointer ea;
1120
1121         g_assert (this != NULL);
1122
1123         va_start(ap, this);
1124
1125         class = this->obj.klass;
1126
1127         ind = va_arg(ap, int) - this->bounds [0].lower_bound;
1128         for (i = 1; i < class->rank; i++) {
1129                 ind = ind*this->bounds [i].length + va_arg(ap, int) -
1130                         this->bounds [i].lower_bound;;
1131         }
1132
1133         esize = mono_array_element_size (class);
1134         ea = (gpointer*)((char*)this->vector + (ind * esize));
1135         //printf ("AADDRESS %p %p %d\n", this, ea, ind);
1136
1137         va_end(ap);
1138
1139         return ea;
1140 }
1141
1142 static MonoArray *
1143 mono_array_new_va (MonoMethod *cm, ...)
1144 {
1145         va_list ap;
1146         guint32 *lengths;
1147         guint32 *lower_bounds;
1148         int pcount = cm->signature->param_count;
1149         int rank = cm->klass->rank;
1150         int i, d;
1151
1152         va_start (ap, cm);
1153
1154         lengths = alloca (sizeof (guint32) * pcount);
1155         for (i = 0; i < pcount; ++i)
1156                 lengths [i] = d = va_arg(ap, int);
1157
1158         if (rank == pcount) {
1159                 /* Only lengths provided. */
1160                 lower_bounds = NULL;
1161         } else {
1162                 g_assert (pcount == (rank * 2));
1163                 /* lower bounds are first. */
1164                 lower_bounds = lengths;
1165                 lengths += rank;
1166         }
1167         va_end(ap);
1168
1169         return mono_array_new_full (cm->klass, lengths, lower_bounds);
1170 }
1171
1172 #define ADD_TREE(t)     do { g_ptr_array_add (forest, (t)); } while (0)
1173 #define PUSH_TREE(t,k)  do { *sp = t; sp++; t->svt = k; } while (0)
1174
1175 #define LOCAL_POS(n)    (1 + n)
1176 #define LOCAL_TYPE(n)   ((header)->locals [(n)])
1177
1178 #define ARG_POS(n)      (firstarg + n)
1179 #define ARG_TYPE(n)     ((n) ? (signature)->params [(n) - (signature)->hasthis] : \
1180                         (signature)->hasthis ? &method->klass->this_arg: (signature)->params [(0)])
1181
1182 static void
1183 create_outstack (MonoFlowGraph *cfg, MonoBBlock *bb, MBTree **stack, int depth)
1184 {
1185         MonoMemPool *mp = cfg->mp;
1186         MBTree **c = stack, *t1, *t2;
1187         GPtrArray *forest = bb->forest;
1188         int i;
1189
1190         g_assert (bb->reached);
1191
1192         if (depth <= 0)
1193                 return;
1194
1195         if (bb->outstack) {
1196                 g_assert (bb->outdepth == depth);
1197                 return;
1198         }
1199
1200         bb->outdepth = depth;
1201         bb->outstack = mono_mempool_alloc (mp, depth * sizeof (MBTree *));
1202         
1203         for (i = 0; i < depth; i++) {
1204                 if ((t1 = mono_store_tree (cfg, i, c [i], &t2)))
1205                         ADD_TREE (t1);
1206                 bb->outstack [i] = t2;
1207         }
1208 }
1209
1210 static void
1211 mark_reached (MonoFlowGraph *cfg, MonoBBlock *target, MBTree **stack, int depth)
1212 {
1213         MonoMemPool *mp = cfg->mp;
1214         int i;
1215
1216         if (target->reached)
1217                 return;
1218
1219         target->reached = 1;
1220
1221         if (depth == 0)
1222                 return;
1223
1224         g_assert (stack);
1225
1226         if (target->instack) {
1227                 g_assert (target->indepth == depth);
1228                 return;
1229         }
1230
1231         target->indepth = depth;
1232         target->instack = mono_mempool_alloc (mp, depth * sizeof (MBTree *));
1233         
1234         for (i = 0; i < depth; i++) {
1235                 target->instack [i] = ctree_create_dup (mp, stack [i]);
1236         }
1237         
1238         
1239 }
1240
1241 #define MARK_REACHED(bb) do { if (!bb->reached) { bb->reached = 1; }} while (0)
1242
1243 /**
1244  * mono_create_cfg:
1245  * @method: the method to analyse
1246  * @mp: a memory pool
1247  * @locals_size: to return the size of local vars
1248  *
1249  * This is the architecture independent part of JIT compilation.
1250  * It creates a forest of trees which can then be fed into the
1251  * architecture dependent code generation.
1252  *
1253  * The algorithm is from Andi Krall, the same is used in CACAO
1254  */
1255 void
1256 mono_analyze_stack (MonoFlowGraph *cfg)
1257 {
1258         MonoMethod *method = cfg->method;
1259         MonoMemPool *mp = cfg->mp;
1260         MonoBytecodeInfo *bcinfo = cfg->bcinfo;
1261         MonoMethodHeader *header;
1262         MonoMethodSignature *signature;
1263         MonoImage *image;
1264         MonoValueType svt;
1265         MBTree **sp, **stack, **arg_sp, *t1, *t2, *t3;
1266         register const unsigned char *ip, *end;
1267         GPtrArray *forest;
1268         int i, j, depth, repeat_count;
1269         int varnum = 0, firstarg = 0, retvtarg = 0;
1270         gboolean repeat, superblock_end;
1271         MonoBBlock *bb, *tbb;
1272
1273         header = ((MonoMethodNormal *)method)->header;
1274         signature = method->signature;
1275         image = method->klass->image; 
1276
1277         sp = stack = alloca (sizeof (MBTree *) * (header->max_stack + 1));
1278         
1279         if (header->num_locals) {
1280                 int size, align;
1281
1282                 for (i = 0; i < header->num_locals; ++i) {
1283                         size = mono_type_size (header->locals [i], &align);
1284                         varnum = arch_allocate_var (cfg, size, align, MONO_LOCALVAR, VAL_UNKNOWN);
1285                 }
1286         }
1287
1288         if (signature->ret->type == MONO_TYPE_VALUETYPE) {
1289                 int size, align;
1290
1291                 size = mono_type_size (signature->ret, &align);
1292                 
1293                 retvtarg = varnum = arch_allocate_var (cfg, size, align, MONO_LOCALVAR, VAL_UNKNOWN);
1294                 
1295                 //printf ("VALUETYPE METHOD %s.%s::%s %d\n", method->klass->name_space, 
1296                 //method->klass->name, method->name, size);
1297         }
1298         
1299         firstarg = varnum + 1;
1300  
1301         if (signature->params_size) {
1302                 int align, size;
1303                 int has_this = signature->hasthis;
1304
1305                 if (has_this) {
1306                         size = align = sizeof (gpointer);
1307                         arch_allocate_var (cfg, size, align, MONO_ARGVAR, VAL_POINTER);
1308                 }
1309
1310                 for (i = 0; i < signature->param_count; ++i) {
1311                         size = mono_type_size (signature->params [i], &align);
1312                         if (size < 4) {
1313                                 size = 4; 
1314                                 align = 4;
1315                         }
1316                         arch_allocate_var (cfg, size, align, MONO_ARGVAR, VAL_UNKNOWN);
1317                 }
1318         }
1319
1320         repeat_count = 0;
1321
1322         do {
1323                 repeat = FALSE;
1324                 superblock_end = TRUE;
1325                 sp = stack;
1326
1327                 //printf ("START\n");
1328                 for (i = 0; i < cfg->block_count; i++) {
1329                         bb = &cfg->bblocks [i];
1330
1331                         //printf ("BBS %d %d %d %d\n", i, bb->reached, bb->finished, superblock_end);
1332                         
1333                         if (!bb->reached && !superblock_end) {
1334                                 MonoBBlock *sbb = &cfg->bblocks [i - 1];
1335
1336                                 g_assert (sbb->outdepth == (sp - stack));
1337
1338                                 mark_reached (cfg, bb, sbb->outstack, sbb->outdepth);
1339                         } 
1340                         
1341                         if (bb->reached) {
1342
1343                                 if (!bb->finished) {
1344
1345                                         sp = stack;
1346
1347                                         for (j = 0; j < bb->indepth; j++) {
1348                                                 sp [j] = bb->instack [j];
1349                                         }
1350                                         sp += bb->indepth;
1351
1352                                         bb->finished = 1;
1353                                 
1354                                         ip = header->code + bb->cli_addr;
1355                                         end = ip + bb->length;
1356
1357                                         bb->forest = forest = g_ptr_array_new ();
1358                                 
1359                                         superblock_end = FALSE;
1360
1361         while (ip < end) {
1362                 guint32 cli_addr = ip - header->code;
1363                                         
1364                 //printf ("%d IL%04x OPCODE %s %d %d %d\n", i, cli_addr, opcode_names [*ip], 
1365                 //forest->len, superblock_end, sp - stack);
1366
1367                 switch (*ip) {
1368                         case CEE_THROW: {
1369                         --sp;
1370                         ip++;
1371                         
1372                         // fixme: 
1373
1374                         t1 = mono_ctree_new_leaf (mp, MB_TERM_NOP);
1375                         ADD_TREE (t1);          
1376                         superblock_end = TRUE;
1377                         break;
1378                 }
1379                 case CEE_BOX: {
1380                         MonoClass *c;
1381                         guint32 token;
1382                         
1383                         --sp;
1384                         ++ip;
1385                         token = read32 (ip);
1386                         ip += 4;
1387                         
1388                         c = mono_class_get (image, token);
1389                         
1390                         t1 = mono_ctree_new_leaf (mp, MB_TERM_NEWOBJ);
1391                         t1->data.p = c;
1392                         t1->svt = VAL_POINTER;
1393
1394                         t1 = mono_store_tree (cfg, -1, t1, &t3);
1395                         g_assert (t1);
1396                         ADD_TREE (t1);
1397
1398                         t1 = ctree_create_dup (mp, t3);
1399                         t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1400                         t2->data.i = sizeof (MonoObject);
1401                         t1 = mono_ctree_new (mp, MB_TERM_ADD, t1, t2);
1402
1403                         t1 = mono_ctree_new (mp, map_stvalue_type (c), t1, *sp);
1404                         ADD_TREE (t1);
1405
1406                         PUSH_TREE (t3, VAL_POINTER);
1407
1408                         break;
1409                 }
1410                 case CEE_UNBOX: {
1411                         guint32 token;
1412
1413                         ++ip;
1414                         token = read32 (ip);
1415                         ip += 4;
1416                         sp--;
1417
1418                         // fixme: add type check
1419
1420                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1421                         t1->data.i = sizeof (MonoObject);
1422                         t1 = mono_ctree_new (mp, MB_TERM_ADD, *sp, t1);
1423
1424                         PUSH_TREE (t1, VAL_POINTER);
1425                         break;
1426                 }
1427                 case CEE_LDLEN: {
1428                         ip++;
1429                         sp--;
1430                         
1431                         t1 = mono_ctree_new (mp, MB_TERM_LDLEN, *sp, NULL);
1432                         PUSH_TREE (t1, VAL_I32);
1433                         break;
1434                 }
1435
1436                 case CEE_LDOBJ: {
1437                         guint32 token;
1438                         MonoClass *c;
1439
1440                         ++ip;
1441                         token = read32 (ip);
1442                         ip += 4;
1443                         sp--;
1444
1445                         c = mono_class_get (image, token);
1446                         g_assert (c->valuetype);
1447
1448                         t1 = ctree_create_load (cfg, &c->byval_arg, *sp, &svt);
1449                         PUSH_TREE (t1, svt);
1450                         break;
1451                 }
1452                 case CEE_LDSTR: {
1453                         MonoObject *o;
1454                         guint32 index;
1455
1456                         ++ip;
1457                         index = mono_metadata_token_index (read32 (ip));
1458                         ip += 4;
1459
1460                         o = (MonoObject *) mono_ldstr (image, index);
1461                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1462                         t1->data.p = o;
1463
1464                         PUSH_TREE (t1, VAL_POINTER);
1465                         break;
1466                 }
1467                 case CEE_LDSFLD:
1468                 case CEE_LDSFLDA: {
1469                         MonoClass *klass;
1470                         MonoClassField *field;
1471                         guint32 token;
1472                         int load_addr = *ip == CEE_LDSFLDA;
1473                         gpointer addr;
1474
1475                         ++ip;
1476                         token = read32 (ip);
1477                         ip += 4;
1478                         
1479                         /* need to handle fieldrefs */
1480                         klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 
1481                                 mono_metadata_typedef_from_field (image, token & 0xffffff));
1482
1483                         if (!klass->inited)
1484                                 mono_jit_init_class (klass);
1485
1486                         field = mono_class_get_field (klass, token);
1487                         g_assert (field);
1488
1489                         addr = MONO_CLASS_STATIC_FIELDS_BASE (klass) + field->offset;
1490
1491                         if (load_addr) {
1492                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
1493                                 t1->data.p = addr;
1494                                 svt = VAL_POINTER;
1495                         } else {
1496                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
1497                                 t1->data.p = addr;
1498                                 t1 = ctree_create_load (cfg, field->type, t1, &svt);
1499                         }
1500
1501                         PUSH_TREE (t1, svt);
1502                         break;
1503                 }
1504                 case CEE_LDFLD:
1505                 case CEE_LDFLDA: {
1506                         MonoClass *klass;
1507                         MonoClassField *field;
1508                         guint32 token;
1509                         int load_addr = *ip == CEE_LDFLDA;
1510
1511                         ++ip;
1512                         token = read32 (ip);
1513                         ip += 4;
1514                         sp--;
1515
1516                         /* need to handle fieldrefs */
1517                         klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 
1518                                 mono_metadata_typedef_from_field (image, token & 0xffffff));
1519
1520                         if (!klass->inited)
1521                                 mono_jit_init_class (klass);
1522
1523                         field = mono_class_get_field (klass, token);
1524                         g_assert (field);
1525
1526                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1527                         
1528                         if (klass->valuetype)
1529                                 t1->data.i = field->offset - sizeof (MonoObject);
1530                         else 
1531                                 t1->data.i = field->offset;
1532
1533                         t1 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t1);
1534
1535                         if (!load_addr)
1536                                 t1 = mono_ctree_new (mp, map_ldind_type (field->type, &svt), t1, NULL);
1537                         else
1538                                 svt = VAL_POINTER;
1539
1540                         PUSH_TREE (t1, svt);
1541                         break;
1542                 }
1543                 case CEE_STSFLD: {
1544                         MonoClass *klass;
1545                         MonoClassField *field;
1546                         guint32 token;
1547                         gpointer addr;
1548
1549                         ++ip;
1550                         token = read32 (ip);
1551                         ip += 4;
1552                         --sp;
1553
1554                         /* need to handle fieldrefs */
1555                         klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 
1556                                 mono_metadata_typedef_from_field (image, token & 0xffffff));
1557
1558                         if (!klass->inited)
1559                                 mono_jit_init_class (klass);
1560
1561                         field = mono_class_get_field (klass, token);
1562                         g_assert (field);
1563
1564                         addr = MONO_CLASS_STATIC_FIELDS_BASE (klass) + field->offset;
1565                         t1 = ctree_create_store (mp, MB_TERM_ADDR_G, *sp, field->type, addr);
1566
1567                         ADD_TREE (t1);
1568                         break;
1569                 }
1570                 case CEE_STFLD: {
1571                         MonoClass *klass;
1572                         MonoClassField *field;
1573                         guint32 token;
1574
1575                         ++ip;
1576                         token = read32 (ip);
1577                         ip += 4;
1578                         sp -= 2;
1579
1580                         /* need to handle fieldrefs */
1581                         klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 
1582                                 mono_metadata_typedef_from_field (image, token & 0xffffff));
1583
1584                         if (!klass->inited)
1585                                 mono_jit_init_class (klass);
1586
1587                         field = mono_class_get_field (klass, token);
1588                         g_assert (field);
1589
1590                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1591                         if (klass->valuetype)
1592                                 t1->data.i = field->offset - sizeof (MonoObject);
1593                         else 
1594                                 t1->data.i = field->offset;
1595
1596                         //printf ("VALUETYPE %d %d %d\n", klass->valuetype, field->offset, t1->data.i);
1597
1598                         t1 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t1);
1599                         t1 = mono_ctree_new (mp, map_stind_type (field->type), t1, sp [1]);
1600
1601                         ADD_TREE (t1);
1602                         break;
1603                 }
1604                 case CEE_LDELEMA: {
1605                         MonoClass *class;
1606                         guint32 esize, token;
1607
1608                         ++ip;
1609                         token = read32 (ip);
1610                         ip += 4;
1611                         sp -= 2;
1612
1613                         class = mono_class_get (image, token);
1614
1615                         if (!class->inited)
1616                                 mono_jit_init_class (class);
1617
1618                         esize = mono_class_instance_size (class);
1619                         if (class->valuetype)
1620                                 esize -= sizeof (MonoObject);
1621
1622                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1623                         t1->data.i = esize;
1624                         t1 = mono_ctree_new (mp, MB_TERM_MUL, sp [1], t1);
1625                         t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1626                         t2->data.i = G_STRUCT_OFFSET (MonoArray, vector);
1627                         t2 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t2);
1628                         t1 = mono_ctree_new (mp, MB_TERM_ADD, t1, t2);
1629
1630                         PUSH_TREE (t1, VAL_POINTER);
1631                         break;
1632                 }
1633                 case CEE_NOP: { 
1634                         ++ip;
1635                         break;
1636                 }
1637                 case CEE_BREAK: { 
1638                         ++ip;
1639                         t1 = mono_ctree_new_leaf (mp, MB_TERM_BREAK);
1640                         ADD_TREE (t1);
1641                         break;
1642                 } 
1643                 case CEE_SWITCH: {
1644                         guint32 i, n;
1645                         MonoBBlock **jt;
1646                         gint32 st, target;
1647
1648                         ++ip;
1649                         n = read32 (ip);
1650                         ip += 4;
1651                         --sp;
1652
1653                         t1 = mono_ctree_new (mp, MB_TERM_SWITCH, *sp, NULL);
1654                         jt = t1->data.p = mono_alloc_static (sizeof (gpointer) * (n + 2));
1655                         st = cli_addr + 5 + 4 * n;
1656                         
1657                         // hack: we store n at position 0
1658                         jt [0] = (MonoBBlock *)n;
1659
1660                         create_outstack (cfg, bb, stack, sp - stack);
1661
1662                         for (i = 1; i <= (n + 1); i++) {
1663                                 if (i > n)
1664                                         target = st;
1665                                 else {
1666                                         target = read32 (ip) + st;
1667                                         ip += 4;
1668                                 }
1669                                 g_assert (target >= 0 && target <= header->code_size);
1670                                 g_assert (bcinfo [target].is_block_start);
1671                                 tbb = &cfg->bblocks [bcinfo [target].block_id];
1672                                 mark_reached (cfg, tbb, stack, sp - stack);
1673                                 jt [i] = tbb; 
1674                         }
1675
1676                         ADD_TREE (t1);
1677                         break;
1678                 }
1679                 case CEE_LDTOKEN: {
1680                         gpointer handle;
1681                         MonoClass *handle_class;
1682
1683                         ++ip;
1684                         handle = mono_ldtoken (image, read32 (ip), &handle_class);
1685                         ip += 4;
1686
1687                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1688                         t1->data.p = handle;
1689                         PUSH_TREE (t1, VAL_POINTER);
1690
1691                         break;
1692                 }
1693                 case CEE_NEWARR: {
1694                         MonoClass *class;
1695                         guint32 token;
1696
1697                         ip++;
1698                         --sp;
1699                         token = read32 (ip);
1700                         class = mono_class_get (image, token);
1701                         ip += 4;
1702
1703                         t1 = mono_ctree_new (mp, MB_TERM_NEWARR, *sp, NULL);
1704                         t1->data.p = class;
1705                         PUSH_TREE (t1, VAL_POINTER);
1706
1707                         break;
1708                 }
1709                 case CEE_CPOBJ: {
1710                         MonoClass *class;
1711                         guint32 token;
1712
1713                         ++ip;
1714                         token = read32 (ip);
1715                         class = mono_class_get (image, token);
1716                         ip += 4;
1717                         sp -= 2;
1718
1719                         t1 = mono_ctree_new (mp, MB_TERM_CPOBJ, sp [0], sp [1]);
1720                         ADD_TREE (t1);
1721                         
1722                         break;
1723                 }
1724                 case CEE_NEWOBJ: {
1725                         MonoMethodSignature *csig;
1726                         MethodCallInfo *ci;
1727                         MonoMethod *cm;
1728                         MBTree *this = NULL;
1729                         guint32 token;
1730                         int i, align, size, args_size = 0;
1731                         int newarr = FALSE;
1732
1733                         ++ip;
1734                         token = read32 (ip);
1735                         ip += 4;
1736
1737                         cm = mono_get_method (image, token, NULL);
1738                         g_assert (cm);
1739                         g_assert (!strcmp (cm->name, ".ctor"));
1740                         
1741                         ci =  mono_mempool_alloc0 (mp, sizeof (MethodCallInfo));
1742                         ci->m = cm;
1743
1744                         csig = cm->signature;
1745                         g_assert (csig->call_convention == MONO_CALL_DEFAULT);
1746                         g_assert (csig->hasthis);
1747                         
1748                         arg_sp = sp -= csig->param_count;
1749
1750                         if (cm->klass->parent == mono_defaults.array_class) {
1751                                 newarr = TRUE;
1752                                 this = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1753                                 this->data.p = cm;
1754                         } else {                                
1755                                 this = mono_ctree_new_leaf (mp, MB_TERM_NEWOBJ);
1756                                 this->data.p = cm->klass;
1757                                 this->svt = VAL_POINTER;
1758
1759                                 t1 = mono_store_tree (cfg, -1, this, &this);
1760                                 g_assert (t1);
1761                                 ADD_TREE (t1);
1762                         }
1763
1764                         for (i = csig->param_count - 1; i >= 0; i--) {
1765                                 t1 = mono_ctree_new (mp, MB_TERM_ARG, arg_sp [i], NULL);        
1766                                 ADD_TREE (t1);
1767                                 size = mono_type_size (cm->signature->params [i], &align);
1768                                 args_size += (size + 3) & ~3;
1769                         }
1770
1771                         args_size += sizeof (gpointer); /* this argument */             
1772                         ci->args_size = args_size;
1773
1774                         if (newarr) {
1775
1776                                 t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1777                                 t2->data.p = mono_array_new_va;
1778
1779                                 t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, this, t2);
1780                                 t1->data.p = ci;
1781                                 t1->svt = VAL_POINTER;
1782
1783                                 t1 = mono_store_tree (cfg, -1, t1, &t2);
1784                                 g_assert (t1);
1785                                 ADD_TREE (t1);
1786                                 PUSH_TREE (t2, t2->svt);
1787
1788                         } else {
1789                                 
1790                                 if (!cm->addr)
1791                                         cm->addr = arch_create_simple_jit_trampoline (cm);
1792
1793                                 t2 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
1794                                 t2->data.p = (char *)cm + G_STRUCT_OFFSET (MonoMethod, addr);
1795                                 t2 = mono_ctree_new (mp, MB_TERM_LDIND_I4, t2, NULL);
1796
1797                                 t1 = mono_ctree_new (mp, map_call_type (csig->ret, &svt), this, t2);
1798                                 t1->data.p = ci;
1799                                 t1->svt = svt;
1800
1801                                 ADD_TREE (t1);                  
1802                                 t1 = ctree_create_dup (mp, this);               
1803                                 PUSH_TREE (t1, t1->svt);
1804
1805                         }
1806                         break;
1807                 }
1808                 case CEE_CALL: 
1809                 case CEE_CALLVIRT: {
1810                         MonoMethodSignature *csig;
1811                         MethodCallInfo *ci;
1812                         MonoMethod *cm;
1813                         MBTree *this = NULL;
1814                         guint32 token;
1815                         int i, align, size, args_size = 0;
1816                         int virtual = *ip == CEE_CALLVIRT;
1817                         gboolean array_set = FALSE;
1818                         gboolean array_get = FALSE;
1819                         gboolean pinvoke = FALSE;
1820                         int nargs, vtype_num = 0;
1821
1822                         ++ip;
1823                         token = read32 (ip);
1824                         ip += 4;
1825
1826                         cm = mono_get_method (image, token, NULL);
1827                         g_assert (cm);
1828
1829                         ci =  mono_mempool_alloc0 (mp, sizeof (MethodCallInfo));
1830                         ci->m = cm;
1831
1832                         if (cm->flags &  METHOD_ATTRIBUTE_PINVOKE_IMPL)
1833                             pinvoke = TRUE;
1834
1835                         if ((cm->flags & METHOD_ATTRIBUTE_FINAL) ||
1836                             !(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
1837                                 virtual = 0;
1838
1839                         csig = cm->signature;
1840                         g_assert (csig->call_convention == MONO_CALL_DEFAULT);
1841                         g_assert (!virtual || csig->hasthis);
1842
1843                         /* fixme: we need to unbox the this pointer for value types */
1844                         g_assert (!virtual || !cm->klass->valuetype);
1845
1846                         nargs = csig->param_count;
1847                         arg_sp = sp -= nargs;
1848                         
1849                         if ((cm->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
1850                             (cm->klass->parent == mono_defaults.array_class)) {
1851                                 if (!strcmp (cm->name, "Set")) { 
1852                                         array_set = TRUE;
1853                                         nargs--;
1854                                 } else if (!strcmp (cm->name, "Get")) 
1855                                         array_get = TRUE;
1856                         }
1857
1858                         for (i = nargs - 1; i >= 0; i--) {
1859                                 if (pinvoke && cm->signature->params [i]->type == MONO_TYPE_STRING) {
1860                                         t1 = mono_ctree_new (mp, MB_TERM_STRING_ARG, arg_sp [i], NULL);
1861                                 } else {
1862                                         t1 = mono_ctree_new (mp, MB_TERM_ARG, arg_sp [i], NULL);
1863                                 }       
1864                                 ADD_TREE (t1);
1865                                 size = mono_type_size (cm->signature->params [i], &align);
1866                                 args_size += (size + 3) & ~3;
1867                         }
1868
1869                         if (csig->hasthis) {
1870                                 this = *(--sp);
1871                                 args_size += sizeof (gpointer);
1872                         } else
1873                                 this = mono_ctree_new_leaf (mp, MB_TERM_NOP);
1874
1875                         if (csig->ret->type == MONO_TYPE_VALUETYPE) {
1876                                 int size, align;
1877                                 if ((size = mono_type_size (csig->ret, &align)) > 4 || size == 3)
1878                                         vtype_num = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, VAL_UNKNOWN);
1879                         }
1880
1881                         ci->args_size = args_size;
1882                         ci->vtype_num = vtype_num;
1883
1884                         if (array_get) {
1885                                 int size, align, vnum;
1886                                 
1887                                 t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1888                                 t2->data.p = ves_array_element_address;
1889
1890                                 t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, this, t2);
1891                                 t1->data.p = ci;
1892
1893                                 t1 = mono_ctree_new (mp, map_ldind_type (csig->ret, &svt), t1, NULL);
1894                                 t1->svt = svt;          
1895
1896                                 mono_get_val_sizes (t1->svt, &size, &align);
1897                                 vnum = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, svt);
1898
1899                                 t2 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
1900                                 t2->data.i = vnum;
1901                                 t1 = mono_ctree_new (mp, map_store_svt_type (svt), t2, t1);
1902                                 t1->svt = svt;
1903
1904                                 ADD_TREE (t1);
1905                                 t1 = ctree_create_dup (mp, t1);
1906                                 PUSH_TREE (t1, t1->svt);
1907
1908                         } else if (array_set) {
1909
1910                                 t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1911                                 t2->data.p = ves_array_element_address;
1912
1913                                 t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, this, t2);
1914                                 t1->data.p = ci;
1915
1916                                 t1 = mono_ctree_new (mp, map_stind_type (csig->params [nargs]), t1, arg_sp [nargs]);
1917                                 ADD_TREE (t1);
1918                         
1919                         } else {
1920
1921                                 if (virtual) {
1922                                         if (!cm->klass->metadata_inited)
1923                                                 mono_class_metadata_init (cm->klass);
1924
1925                                         if (cm->klass->flags & TYPE_ATTRIBUTE_INTERFACE)
1926                                                 t2 = mono_ctree_new_leaf (mp, MB_TERM_INTF_ADDR);
1927                                         else 
1928                                                 t2 = mono_ctree_new_leaf (mp, MB_TERM_VFUNC_ADDR);
1929          
1930                                         t2->data.m = cm;
1931
1932                                 } else {
1933                                 
1934                                         if (!cm->addr)
1935                                                 cm->addr = arch_create_simple_jit_trampoline (cm);
1936                                 
1937                                         t2 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
1938                                         t2->data.p = (char *)cm + G_STRUCT_OFFSET (MonoMethod, addr);
1939                                         t2 = mono_ctree_new (mp, MB_TERM_LDIND_I4, t2, NULL);
1940                                 }
1941
1942                                 t1 = mono_ctree_new (mp, map_call_type (csig->ret, &svt), this, t2);
1943                                 t1->data.p = ci;
1944                                 t1->svt = svt;
1945
1946                                 if (csig->ret->type != MONO_TYPE_VOID) {
1947
1948                                         if (vtype_num) {
1949                                                 ADD_TREE (t1);
1950                                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_VTYPE);
1951                                                 t1->data.i = vtype_num;
1952                                                 PUSH_TREE (t1, VAL_UNKNOWN); 
1953                                         } else {
1954                                                 t1 = mono_store_tree (cfg, -1, t1, &t2);
1955                                                 g_assert (t1);
1956                                                 ADD_TREE (t1);
1957                                                 PUSH_TREE (t2, t2->svt);
1958                                         }
1959                                 } else
1960                                         ADD_TREE (t1);
1961    
1962                         }
1963
1964                         break;
1965                 }
1966                 case CEE_ISINST:
1967                 case CEE_CASTCLASS: {
1968                         guint32 token;
1969                         ++ip;
1970                         token = read32 (ip);
1971                         
1972                         /* fixme: do something */
1973
1974                         ip += 4;
1975                         break;
1976                 }
1977                 case CEE_LDC_I4_S: { 
1978                         ++ip;
1979                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1980                         t1->data.i = *(gint8 *)ip;
1981                         ++ip;
1982                         PUSH_TREE (t1, VAL_I32);
1983                         break;
1984                 }
1985                 case CEE_LDC_I4: { 
1986                         ++ip;
1987                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
1988                         t1->data.i = read32 (ip);
1989                         ip += 4;
1990                         PUSH_TREE (t1, VAL_I32);
1991                         break;
1992                 }
1993                 case CEE_LDC_I4_M1:
1994                 case CEE_LDC_I4_0:
1995                 case CEE_LDC_I4_1:
1996                 case CEE_LDC_I4_2:
1997                 case CEE_LDC_I4_3:
1998                 case CEE_LDC_I4_4:
1999                 case CEE_LDC_I4_5:
2000                 case CEE_LDC_I4_6:
2001                 case CEE_LDC_I4_7:
2002                 case CEE_LDC_I4_8: {
2003                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
2004                         t1->data.i = (*ip) - CEE_LDC_I4_0;
2005                         ++ip;
2006                         PUSH_TREE (t1, VAL_I32);
2007                         break;
2008                 }
2009                 case CEE_LDNULL: {
2010                         //fixme: don't know if this is portable ?
2011                         ++ip;
2012                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
2013                         t1->data.i = 0;
2014                         PUSH_TREE (t1, VAL_I32);
2015                         break;
2016                 }
2017                 case CEE_LDC_I8: {
2018                         ++ip;
2019                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I8);
2020                         t1->data.l = read64 (ip);
2021                         ip += 8;
2022                         PUSH_TREE (t1, VAL_I64);                
2023                         break;
2024                 }
2025                 case CEE_LDC_R4: {
2026                         float *f = mono_alloc_static (sizeof (float));
2027                         ++ip;
2028                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_R4);
2029                         readr4 (ip, f);
2030                         t1->data.p = f;
2031                         ip += 4;
2032                         PUSH_TREE (t1, VAL_DOUBLE);             
2033                         break;
2034                 }
2035                 case CEE_LDC_R8: { 
2036                         double *d = mono_alloc_static (sizeof (double));
2037                         ++ip;
2038                         t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_R8);
2039                         readr8 (ip, d);
2040                         t1->data.p = d;
2041                         ip += 8;
2042                         PUSH_TREE (t1, VAL_DOUBLE);             
2043                         break;
2044                 }
2045                 case CEE_LDLOC_0:
2046                 case CEE_LDLOC_1:
2047                 case CEE_LDLOC_2:
2048                 case CEE_LDLOC_3: {
2049                         int n = (*ip) - CEE_LDLOC_0;
2050                         ++ip;
2051
2052                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2053                         t1->data.i = LOCAL_POS (n);
2054                         t1 = ctree_create_load (cfg, LOCAL_TYPE (n), t1, &svt);
2055
2056                         PUSH_TREE (t1, svt);
2057                         break;
2058                 }
2059                 case CEE_LDLOC_S: {
2060                         ++ip;
2061                         
2062                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2063                         t1->data.i = LOCAL_POS (*ip);
2064                         t1 = ctree_create_load (cfg, LOCAL_TYPE (*ip), t1, &svt);
2065                         ++ip;
2066
2067                         PUSH_TREE (t1, svt);
2068                         break;
2069                 }
2070                 case CEE_LDLOCA_S: {
2071                         ++ip;
2072
2073                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2074                         t1->data.p = (gpointer)LOCAL_POS (*ip);
2075                         ++ip;
2076                         PUSH_TREE (t1, VAL_POINTER);                    
2077                         break;
2078                 }
2079                 case CEE_STLOC_0:
2080                 case CEE_STLOC_1:
2081                 case CEE_STLOC_2:
2082                 case CEE_STLOC_3: {
2083                         int n = (*ip) - CEE_STLOC_0;
2084                         ++ip;
2085                         --sp;
2086
2087                         t1 = ctree_create_store (mp, MB_TERM_ADDR_L, *sp, LOCAL_TYPE (n), 
2088                                                  (gpointer)LOCAL_POS (n));
2089
2090                         ADD_TREE (t1);                  
2091                         break;
2092                 }
2093                 case CEE_STLOC_S: {
2094                         ++ip;
2095                         --sp;
2096
2097                         t1 = ctree_create_store (mp, MB_TERM_ADDR_L, *sp, LOCAL_TYPE (*ip), 
2098                                                  (gpointer)LOCAL_POS (*ip));
2099                         ++ip;
2100
2101                         ADD_TREE (t1);                  
2102                         break;
2103                 }
2104
2105                 MAKE_BI_ALU (ADD)
2106                 MAKE_BI_ALU (SUB)
2107                 MAKE_BI_ALU (AND)
2108                 MAKE_BI_ALU (OR)
2109                 MAKE_BI_ALU (XOR)
2110                 MAKE_BI_ALU (SHL)
2111                 MAKE_BI_ALU (SHR)
2112                 MAKE_BI_ALU (SHR_UN)
2113                 MAKE_BI_ALU (MUL)
2114                 MAKE_BI_ALU (DIV)
2115                 MAKE_BI_ALU (DIV_UN)
2116                 MAKE_BI_ALU (REM)
2117                 MAKE_BI_ALU (REM_UN)
2118
2119                 MAKE_LDIND (LDIND_I1,  MB_TERM_LDIND_I1, VAL_I32)
2120                 MAKE_LDIND (LDIND_U1,  MB_TERM_LDIND_U1, VAL_I32)
2121                 MAKE_LDIND (LDIND_I2,  MB_TERM_LDIND_I2, VAL_I32)
2122                 MAKE_LDIND (LDIND_U2,  MB_TERM_LDIND_U2, VAL_I32)
2123                 MAKE_LDIND (LDIND_I,   MB_TERM_LDIND_I4, VAL_I32)
2124                 MAKE_LDIND (LDIND_I4,  MB_TERM_LDIND_I4, VAL_I32)
2125                 MAKE_LDIND (LDIND_REF, MB_TERM_LDIND_U4, VAL_I32)
2126                 MAKE_LDIND (LDIND_U4,  MB_TERM_LDIND_U4, VAL_I32)
2127                 MAKE_LDIND (LDIND_I8,  MB_TERM_LDIND_I8, VAL_I64)
2128                 MAKE_LDIND (LDIND_R4,  MB_TERM_LDIND_R4, VAL_DOUBLE)
2129                 MAKE_LDIND (LDIND_R8,  MB_TERM_LDIND_R8, VAL_DOUBLE)
2130
2131                 MAKE_STIND (STIND_I1,  MB_TERM_STIND_I1)
2132                 MAKE_STIND (STIND_I2,  MB_TERM_STIND_I2)
2133                 MAKE_STIND (STIND_I,   MB_TERM_STIND_I4)
2134                 MAKE_STIND (STIND_I4,  MB_TERM_STIND_I4)
2135                 MAKE_STIND (STIND_I8,  MB_TERM_STIND_I8)
2136                 MAKE_STIND (STIND_R4,  MB_TERM_STIND_R4)
2137                 MAKE_STIND (STIND_R8,  MB_TERM_STIND_R8)
2138                 MAKE_STIND (STIND_REF, MB_TERM_STIND_I4)
2139
2140                 MAKE_LDELEM (LDELEM_I1,  MB_TERM_LDIND_I1, VAL_I32, 1)
2141                 MAKE_LDELEM (LDELEM_U1,  MB_TERM_LDIND_U1, VAL_I32, 1)
2142                 MAKE_LDELEM (LDELEM_I2,  MB_TERM_LDIND_I2, VAL_I32, 2)
2143                 MAKE_LDELEM (LDELEM_U2,  MB_TERM_LDIND_U2, VAL_I32, 2)
2144                 MAKE_LDELEM (LDELEM_I,   MB_TERM_LDIND_I4, VAL_I32, 4)
2145                 MAKE_LDELEM (LDELEM_I4,  MB_TERM_LDIND_I4, VAL_I32, 4)
2146                 MAKE_LDELEM (LDELEM_REF, MB_TERM_LDIND_U4, VAL_I32, 4)
2147                 MAKE_LDELEM (LDELEM_U4,  MB_TERM_LDIND_U4, VAL_I32, 4)
2148                 MAKE_LDELEM (LDELEM_I8,  MB_TERM_LDIND_I8, VAL_I64, 8)
2149                 MAKE_LDELEM (LDELEM_R4,  MB_TERM_LDIND_R4, VAL_DOUBLE, 4)
2150                 MAKE_LDELEM (LDELEM_R8,  MB_TERM_LDIND_R8, VAL_DOUBLE, 8)
2151
2152                 MAKE_STELEM (STELEM_I1,  MB_TERM_STIND_I1, 1)
2153                 MAKE_STELEM (STELEM_I2,  MB_TERM_STIND_I2, 2)
2154                 MAKE_STELEM (STELEM_I4,  MB_TERM_STIND_I4, 4)
2155                 MAKE_STELEM (STELEM_I,   MB_TERM_STIND_I4, 4)
2156                 MAKE_STELEM (STELEM_REF, MB_TERM_STIND_I4, 4)
2157                 MAKE_STELEM (STELEM_I8,  MB_TERM_STIND_I8, 8)
2158                 MAKE_STELEM (STELEM_R4,  MB_TERM_STIND_R4, 4)
2159                 MAKE_STELEM (STELEM_R8,  MB_TERM_STIND_R8, 8)
2160
2161                 case CEE_NEG: {
2162                         ip++;
2163                         sp--;
2164                         t1 = mono_ctree_new (mp, MB_TERM_NEG, sp [0], NULL);
2165                         PUSH_TREE (t1, sp [0]->svt);            
2166                         break;
2167                 }
2168                 case CEE_NOT: {
2169                         ip++;
2170                         sp--;
2171                         t1 = mono_ctree_new (mp, MB_TERM_NOT, sp [0], NULL);
2172                         PUSH_TREE (t1, sp [0]->svt);
2173                         break;
2174                 }
2175                 case CEE_BR_S: {
2176                         gint32 target;
2177
2178                         ++ip;
2179                         t1 = mono_ctree_new_leaf (mp, MB_TERM_BR);
2180                         target = cli_addr + 2 + (signed char) *ip;
2181  
2182                         g_assert (target >= 0 && target <= header->code_size);
2183                         g_assert (bcinfo [target].is_block_start);
2184                         tbb = &cfg->bblocks [bcinfo [target].block_id];
2185                         create_outstack (cfg, bb, stack, sp - stack);
2186                         mark_reached (cfg, tbb, bb->outstack, bb->outdepth);
2187
2188                         t1->data.p = tbb;
2189                         ADD_TREE (t1);
2190                         ++ip;
2191
2192                         superblock_end = TRUE;
2193                         break;
2194                 }
2195                 case CEE_BR: {
2196                         gint32 target;
2197
2198                         ++ip;
2199                         t1 = mono_ctree_new_leaf (mp, MB_TERM_BR);
2200                         target = cli_addr + 5 + (gint32) read32(ip);
2201
2202                         g_assert (target >= 0 && target <= header->code_size);
2203                         g_assert (bcinfo [target].is_block_start);
2204                         tbb = &cfg->bblocks [bcinfo [target].block_id];
2205                         create_outstack (cfg, bb, stack, sp - stack);
2206                         mark_reached (cfg, tbb, bb->outstack, bb->outdepth);
2207                       
2208                         t1->data.p = tbb;
2209                         ADD_TREE (t1);
2210                         ip += 4;
2211
2212                         superblock_end = TRUE;
2213                         break;
2214                 }
2215
2216                 MAKE_CJUMP(BGT)
2217                 MAKE_CJUMP(BGT_UN)
2218                 MAKE_CJUMP(BLT)
2219                 MAKE_CJUMP(BLT_UN)
2220                 MAKE_CJUMP(BNE_UN)
2221                 MAKE_CJUMP(BEQ)
2222                 MAKE_CJUMP(BGE)
2223                 MAKE_CJUMP(BGE_UN)
2224                 MAKE_CJUMP(BLE)
2225                 MAKE_CJUMP(BLE_UN)
2226
2227                 case CEE_BRTRUE:
2228                 case CEE_BRTRUE_S: {
2229                         gint32 target;
2230                         int near_jump = *ip == CEE_BRTRUE_S;
2231                         ++ip;
2232                         --sp;
2233
2234                         t1 = mono_ctree_new (mp, MB_TERM_BRTRUE, sp [0], NULL);
2235
2236                         if (near_jump)
2237                                 target = cli_addr + 2 + (signed char) *ip;
2238                         else 
2239                                 target = cli_addr + 5 + (gint32) read32 (ip);
2240
2241                         g_assert (target >= 0 && target <= header->code_size);
2242                         g_assert (bcinfo [target].is_block_start);
2243                         tbb = &cfg->bblocks [bcinfo [target].block_id];
2244                         create_outstack (cfg, bb, stack, sp - stack);
2245                         mark_reached (cfg, tbb, bb->outstack, bb->outdepth);
2246   
2247                         t1->data.p = tbb;
2248                         ip += near_jump ? 1: 4;
2249                         ADD_TREE (t1);
2250                         break;
2251                 }
2252                 case CEE_BRFALSE:
2253                 case CEE_BRFALSE_S: {
2254                         gint32 target;
2255                         int near_jump = *ip == CEE_BRFALSE_S;
2256                         ++ip;
2257                         --sp;
2258
2259                         t1 = mono_ctree_new (mp, MB_TERM_BRFALSE, sp [0], NULL);
2260
2261                         if (near_jump)
2262                                 target = cli_addr + 2 + (signed char) *ip;
2263                         else 
2264                                 target = cli_addr + 5 + (gint32) read32 (ip);
2265
2266                         g_assert (target >= 0 && target <= header->code_size);
2267                         g_assert (bcinfo [target].is_block_start);
2268                         tbb = &cfg->bblocks [bcinfo [target].block_id];
2269                         create_outstack (cfg, bb, stack, sp - stack);
2270                         mark_reached (cfg, tbb, bb->outstack, bb->outdepth);
2271                     
2272                         t1->data.p = tbb;
2273                         ip += near_jump ? 1: 4;
2274                         ADD_TREE (t1);
2275                         break;
2276                 }
2277                 case CEE_RET: {
2278                         ip++;
2279
2280                         if (signature->ret->type != MONO_TYPE_VOID) {
2281                                 --sp;
2282                                 t1 = mono_ctree_new (mp, MB_TERM_RETV, *sp, NULL);
2283                         } else {
2284                                 t1 = mono_ctree_new (mp, MB_TERM_RET, NULL, NULL);
2285                         }
2286
2287                         t1->last_instr = (ip == end);
2288
2289                         ADD_TREE (t1);
2290
2291                         if (sp > stack) {
2292                                 g_warning ("more values on stack at IL_%04x: %d",  ip - header->code, sp - stack);
2293                                 mono_print_ctree (sp [-1]);
2294                                 printf ("\n");
2295                         }
2296                         superblock_end = TRUE;
2297                         break;
2298                 }
2299                 case CEE_LDARG_0:
2300                 case CEE_LDARG_1:
2301                 case CEE_LDARG_2:
2302                 case CEE_LDARG_3: {
2303                         int n = (*ip) - CEE_LDARG_0;
2304                         ++ip;
2305
2306                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2307                         t1->data.i = ARG_POS (n);
2308                         t1 = ctree_create_load (cfg, ARG_TYPE (n), t1, &svt);
2309                         PUSH_TREE (t1, svt);
2310                         break;
2311                 }
2312                 case CEE_LDARG_S: {
2313                         ++ip;
2314
2315                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2316                         t1->data.i = ARG_POS (*ip);
2317                         t1 = ctree_create_load (cfg, ARG_TYPE (*ip), t1, &svt);
2318                         PUSH_TREE (t1, svt);
2319                         ++ip;
2320                         break;
2321                 }
2322                 case CEE_LDARGA_S: {
2323                         ++ip;
2324
2325                         t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2326                         t1->data.i = ARG_POS (*ip);
2327                         PUSH_TREE (t1, VAL_POINTER);
2328                         ++ip;
2329                         break;
2330                 }
2331                 case CEE_STARG_S: {
2332                         ++ip;
2333                         --sp;
2334
2335                         t1 = ctree_create_store (mp, MB_TERM_ADDR_L, *sp, ARG_TYPE (*ip), 
2336                                                  (gpointer)ARG_POS (*ip));
2337                         ++ip;
2338
2339                         ADD_TREE (t1);                  
2340                         break;
2341                 }
2342                 case CEE_DUP: {
2343                         ++ip; 
2344                         sp--;
2345                         /* fixme: IMO we can use the temp. variable associated
2346                          * with the current slot instead of -1 
2347                          */
2348                         if ((t2 = mono_store_tree (cfg, -1, *sp, &t1)) != NULL)
2349                                 ADD_TREE (t2);
2350
2351                         PUSH_TREE (t1, t1->svt);
2352                         t1 = ctree_create_dup (mp, t1);         
2353                         PUSH_TREE (t1, t1->svt);
2354
2355                         break;
2356                 }
2357                 case CEE_POP: {
2358                         ++ip;
2359                         --sp;
2360
2361                         t1 = mono_ctree_new (mp, MB_TERM_POP, *sp, NULL);
2362                         ADD_TREE (t1);
2363
2364                         break;
2365                 }
2366                 case CEE_CONV_U1: 
2367                 case CEE_CONV_I1: {
2368                         ++ip;
2369                         sp--;
2370                         t1 = mono_ctree_new (mp, MB_TERM_CONV_I1, *sp, NULL);
2371                         PUSH_TREE (t1, VAL_I32);                
2372                         break;
2373                 }
2374                 case CEE_CONV_U2: 
2375                 case CEE_CONV_I2: {
2376                         ++ip;
2377                         sp--;
2378                         t1 = mono_ctree_new (mp, MB_TERM_CONV_I2, *sp, NULL);
2379                         PUSH_TREE (t1, VAL_I32);                
2380                         break;
2381                 }
2382                 case CEE_CONV_I: 
2383                 case CEE_CONV_U: 
2384                 case CEE_CONV_U4: 
2385                 case CEE_CONV_I4: {
2386                         ++ip;
2387                         sp--;
2388                         t1 = mono_ctree_new (mp, MB_TERM_CONV_I4, *sp, NULL);
2389                         PUSH_TREE (t1, VAL_I32);                
2390                         break;
2391                 }
2392                 case CEE_CONV_I8: {
2393                         ++ip;
2394                         sp--;
2395                         t1 = mono_ctree_new (mp, MB_TERM_CONV_I8, *sp, NULL);
2396                         PUSH_TREE (t1, VAL_I64);                
2397                         break;
2398                 }
2399                 case CEE_CONV_U8: {
2400                         ++ip;
2401                         sp--;
2402                         t1 = mono_ctree_new (mp, MB_TERM_CONV_I8, *sp, NULL);
2403                         PUSH_TREE (t1, VAL_I64);                
2404                         break;
2405                 }
2406                 case CEE_CONV_R8: {
2407                         ++ip;
2408                         sp--;
2409                         t1 = mono_ctree_new (mp, MB_TERM_CONV_R8, *sp, NULL);
2410                         PUSH_TREE (t1, VAL_DOUBLE);             
2411                         break;
2412                 }
2413                 case CEE_CONV_OVF_U4: {
2414                         // fixme: raise exceptions ?
2415                         ++ip;
2416                         sp--;
2417                         t1 = mono_ctree_new (mp, MB_TERM_CONV_I4, *sp, NULL);
2418                         PUSH_TREE (t1, VAL_I32);                
2419                         break;
2420                 }
2421                 case CEE_CONV_OVF_I4_UN: {
2422                         // fixme: raise exceptions ?
2423                         ++ip;
2424                         sp--;
2425                         t1 = mono_ctree_new (mp, MB_TERM_CONV_I4, *sp, NULL);
2426                         PUSH_TREE (t1, VAL_I32);                
2427                         break;
2428                 }
2429                 case CEE_CONV_OVF_U4_UN: {
2430                         // fixme: raise exceptions ?
2431                         ++ip;
2432                         sp--;
2433                         t1 = mono_ctree_new (mp, MB_TERM_CONV_I4, *sp, NULL);
2434                         PUSH_TREE (t1, VAL_I32);                
2435                         break;
2436                 }
2437                 case 0xFE: {
2438                         ++ip;                   
2439                         switch (*ip) {
2440                                 
2441                         MAKE_BI_ALU (CEQ)
2442                         MAKE_BI_ALU (CLT)
2443
2444                         case CEE_INITOBJ: {
2445                                 MonoClass *class;
2446                                 guint32 token;
2447                                 
2448                                 ++ip;
2449                                 token = read32 (ip);
2450                                 class = mono_class_get (image, token);
2451                                 ip += 4;
2452                                 sp--;
2453                                 
2454                                 t1 = mono_ctree_new (mp, MB_TERM_INITOBJ, *sp, NULL);
2455                                 t1->data.i = mono_class_value_size (class, NULL);
2456                                 ADD_TREE (t1);
2457
2458                                 break;
2459                         }
2460                         case CEE_LDARG: {
2461                                 guint32 n;
2462                                 ++ip;
2463                                 n = read32 (ip);
2464                                 ip += 4;
2465
2466                                 t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
2467                                 t1->data.i = ARG_POS (n);
2468                                 t1 = ctree_create_load (cfg, ARG_TYPE (n), t1, &svt);
2469                                 PUSH_TREE (t1, svt);
2470                                 break;
2471                         }
2472                         default:
2473                                 g_error ("Unimplemented opcode at IL_%04x "
2474                                          "0xFE %02x", ip - header->code, *ip);
2475                         }
2476                         break;
2477                 }       
2478                 default:
2479                         g_warning ("unknown instruction `%s' at IL_%04X", 
2480                                    opcode_names [*ip], ip - header->code);
2481                         mono_print_forest (forest);
2482                         g_assert_not_reached ();
2483                 }
2484         }               
2485
2486         if ((depth = sp - stack)) {
2487                 create_outstack (cfg, bb, stack, sp - stack);
2488                 //mono_print_forest (forest);
2489                 //printf ("DEPTH %d %d\n", depth, sp [0]->op);
2490         }
2491
2492                                 } else 
2493                                         superblock_end = TRUE;
2494
2495                         } else {
2496                                 superblock_end = TRUE;
2497                                 //printf ("unreached block %d\n", i);
2498                                 repeat = TRUE;
2499                                 g_assert (repeat_count < 10);
2500                         }
2501                                 //printf ("BBE %d %d %d %d\n", i, bb->reached, bb->finished, superblock_end);
2502                 }
2503
2504                 repeat_count++;
2505                 //printf ("REPEAT %d\n", repeat);
2506
2507
2508         } while (repeat);
2509
2510         //printf ("FINISHED\n");
2511 }
2512
2513 /* this function is never called */
2514 static void 
2515 ves_array_set (MonoArray *this, ...)
2516 {
2517         g_assert_not_reached ();
2518 }
2519
2520 /* this function is never called */
2521 static void 
2522 ves_array_get (MonoArray *this, ...)
2523 {
2524         g_assert_not_reached ();
2525 }
2526         
2527 /**
2528  * mono_jit_assembly:
2529  * @assembly: reference to an assembly
2530  *
2531  * JIT compilation of all methods in the assembly. Prints debugging
2532  * information on stdout.
2533  */
2534 static void
2535 mono_jit_assembly (MonoAssembly *assembly)
2536 {
2537         MonoImage *image = assembly->image;
2538         MonoMethod *method;
2539         MonoTableInfo *t = &image->tables [MONO_TABLE_METHOD];
2540         int i;
2541
2542         for (i = 0; i < t->rows; i++) {
2543
2544                 method = mono_get_method (image, 
2545                                           (MONO_TABLE_METHOD << 24) | (i + 1), 
2546                                           NULL);
2547
2548                 printf ("\nMethod: %s\n\n", method->name);
2549
2550                 if (method->flags & METHOD_ATTRIBUTE_ABSTRACT)
2551                         printf ("ABSTARCT\n");
2552                 else
2553                         arch_compile_method (method);
2554
2555         }
2556
2557 }
2558
2559 typedef int (*MonoMainIntVoid) ();
2560
2561 /**
2562  * mono_jit_exec:
2563  * @assembly: reference to an assembly
2564  * @argc: argument count
2565  * @argv: argument vector
2566  *
2567  * Start execution of a program.
2568  */
2569 static int 
2570 mono_jit_exec (MonoAssembly *assembly, int argc, char *argv[])
2571 {
2572         MonoImage *image = assembly->image;
2573         MonoCLIImageInfo *iinfo;
2574         MonoMethod *method;
2575         int res = 0;
2576
2577         iinfo = image->image_info;
2578         method = mono_get_method (image, iinfo->cli_cli_header.ch_entry_point, NULL);
2579
2580         if (method->signature->param_count) {
2581                 g_warning ("Main () with arguments not yet supported");
2582                 exit (1);
2583         } else {
2584                 MonoMainIntVoid mfunc;
2585
2586                 mfunc = arch_compile_method (method);
2587                 res = mfunc ();
2588         }
2589         
2590         return res;
2591 }
2592
2593 static void
2594 usage (char *name)
2595 {
2596         fprintf (stderr,
2597                  "%s %s, the Mono ECMA CLI JIT Compiler, (C) 2001 Ximian, Inc.\n\n"
2598                  "Usage is: %s [options] executable args...\n", name,  VERSION, name);
2599         fprintf (stderr,
2600                  "Valid Options are:\n"
2601                  "-d            debug the jit, show disassembler output.\n"
2602                  "--dump-asm    dumps the assembly code generated\n"
2603                  "--dump-forest dumps the reconstructed forest\n"
2604                  "--trace-calls printf function call trace\n"
2605                  "--help        print this help message\n");
2606         exit (1);
2607 }
2608
2609 int 
2610 main (int argc, char *argv [])
2611 {
2612         MonoAssembly *assembly;
2613         int retval = 0, i;
2614         char *file;
2615         gboolean testjit = FALSE;
2616
2617         if (argc < 2)
2618                 usage (argv [0]);
2619
2620         for (i = 1; i < argc && argv [i][0] == '-'; i++){
2621                 if (strcmp (argv [i], "--help") == 0) {
2622                         usage (argv [0]);
2623                 } else if (strcmp (argv [i], "-d") == 0) {
2624                         testjit = TRUE;
2625                         mono_jit_dump_asm = TRUE;
2626                         mono_jit_dump_forest = TRUE;
2627                 } else if (strcmp (argv [i], "--dump-asm") == 0)
2628                         mono_jit_dump_asm = TRUE;
2629                 else if (strcmp (argv [i], "--dump-forest") == 0)
2630                         mono_jit_dump_forest = TRUE;
2631                 else if (strcmp (argv [i], "--trace-calls") == 0)
2632                         mono_jit_trace_calls = TRUE;
2633                 else
2634                         usage (argv [0]);
2635         }
2636         
2637         file = argv [i];
2638
2639         if (!file)
2640                 usage (argv [0]);
2641
2642         mono_init ();
2643         mono_init_icall ();
2644         mono_add_internal_call ("__array_Set", ves_array_set);
2645         mono_add_internal_call ("__array_Get", ves_array_get);
2646
2647         mono_install_trampoline (arch_create_jit_trampoline);
2648
2649         assembly = mono_assembly_open (file, NULL, NULL);
2650         if (!assembly){
2651                 fprintf (stderr, "Can not open image %s\n", file);
2652                 exit (1);
2653         }
2654
2655         if (testjit) {
2656                 mono_jit_assembly (assembly);
2657         } else {
2658                 retval = mono_jit_exec (assembly, argc, argv);
2659                 printf ("RESULT: %d\n", retval);
2660         }
2661
2662         mono_assembly_close (assembly);
2663
2664         return retval;
2665 }
2666
2667
2668