2001-11-09 Dietmar Maurer <dietmar@ximian.com>
authorDietmar Maurer <dietmar@mono-cvs.ximian.com>
Fri, 9 Nov 2001 06:28:41 +0000 (06:28 -0000)
committerDietmar Maurer <dietmar@mono-cvs.ximian.com>
Fri, 9 Nov 2001 06:28:41 +0000 (06:28 -0000)
* testjit.c (mono_analyze_stack): finished array support

2001-11-08  Dietmar Maurer  <dietmar@ximian.com>

* testjit.c (MAKE_STELEM, MAKE_LDELEM): we build a tree which
represents the address of the element. This way we can emit highly
optimized x86 instructions to access elements (using base+index+offset
adressing mode)

svn path=/trunk/mono/; revision=1305

mono/jit/ChangeLog
mono/jit/emit-x86.c
mono/jit/jit.c
mono/jit/testjit.c
mono/jit/x86.brg
mono/tests/array.cs

index 147a916a6d5d8a3bb80db5150ad09d32b22404e6..d7a7a252e22dabf3effa8e1b38d9a396a0591b5c 100644 (file)
@@ -1,3 +1,14 @@
+2001-11-09  Dietmar Maurer  <dietmar@ximian.com>
+
+       * testjit.c (mono_analyze_stack): finished array support
+
+2001-11-08  Dietmar Maurer  <dietmar@ximian.com>
+
+       * testjit.c (MAKE_STELEM, MAKE_LDELEM): we build a tree which
+       represents the address of the element. This way we can emit highly
+       optimized x86 instructions to access elements (using base+index+offset
+       adressing mode)
+
 2001-11-07  Miguel de Icaza  <miguel@ximian.com>
 
        * mempool.c: Include string.h to kill warning.
index e5778ca8f89f24f95dac1fba3bd1fefb9379a9b7..4a7ddbdfbdc0c97b8f37c1427bbf37b5e49ea9d1 100644 (file)
@@ -37,7 +37,7 @@ enter_method (MonoMethod *method, gpointer ebp)
        if (method->signature->hasthis) {
                o = *((MonoObject **)ebp);
                class = o->klass;
-               printf ("%p[%s.%s], ", o, class->name_space, class->name);
+               printf ("this:%p[%s.%s], ", o, class->name_space, class->name);
                ebp += sizeof (gpointer);
        }
 
@@ -431,8 +431,11 @@ tree_allocate_regs (MBTree *tree, int goal, MonoRegSet *rs)
                break;
        }
 
+       //printf ("RALLOC START %d %p %d\n",  tree->op, rs->free_mask, goal);
+
        for (i = 0; nts [i]; i++)
-               tree_allocate_regs (kids [i], nts [i], rs);
+               if (kids [i] != tree) /* don't allocate regs for chain rules */
+                       tree_allocate_regs (kids [i], nts [i], rs);
 
        for (i = 0; nts [i]; i++) {
                if (kids [i] != tree) { /* we do not free register for chain rules */
@@ -448,7 +451,6 @@ tree_allocate_regs (MBTree *tree, int goal, MonoRegSet *rs)
                        g_warning ("register allocation failed %d 0x%08x 0x%08x\n",  tree->reg1, rs->free_mask, tree->exclude_mask);
                        g_assert_not_reached ();
                }
-
                break;
 
        case MB_NTERM_lreg:
@@ -464,15 +466,17 @@ tree_allocate_regs (MBTree *tree, int goal, MonoRegSet *rs)
        case MB_NTERM_freg:
                /* fixme: allocate floating point registers */
                break;
-
-               /*
+      
        case MB_NTERM_addr:
                if (tree->op == MB_TERM_ADD) {
                        tree->reg1 = mono_regset_alloc_reg (rs, tree->left->reg1, tree->exclude_mask);
                        tree->reg2 = mono_regset_alloc_reg (rs, tree->right->reg1, tree->exclude_mask);
                }
+               if (tree->op == MB_TERM_CALL_I4) {
+                       tree->reg1 = mono_regset_alloc_reg (rs, tree->left->reg1, tree->exclude_mask);
+               }
                break;
-               */
+               
        case MB_NTERM_base:
                if (tree->op == MB_TERM_ADD) {
                        tree->reg1 = mono_regset_alloc_reg (rs, tree->left->reg1, tree->exclude_mask);
@@ -490,6 +494,7 @@ tree_allocate_regs (MBTree *tree, int goal, MonoRegSet *rs)
                /* do nothing */
        }
 
+       //printf ("RALLOC END %d %p\n",  tree->op, rs->free_mask);
        tree->emit = mono_burg_func [ern];
 }
 
@@ -507,6 +512,7 @@ arch_allocate_regs (MonoFlowGraph *cfg)
                        //printf ("AREGSTART %d:%d %p\n", i, j, cfg->rs->free_mask);
                        tree_allocate_regs (t1, 1, cfg->rs);
                        //printf ("AREGENDT %d:%d %p\n", i, j, cfg->rs->free_mask);
+                       g_assert (cfg->rs->free_mask == 0xffffffff);
                }
        }
 }
@@ -610,7 +616,6 @@ arch_compile_method (MonoMethod *method)
        g_assert (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL));
 
        //g_assert (!method->addr);
-
        printf ("Start JIT compilation %p %p\n", method, method->addr);
        printf ("Start JIT compilation of %s.%s:%s\n", method->klass->name_space,
                method->klass->name, method->name);
index 661a24764eef045f561391c082a18a6d7d8eec1f..7ffd9b5b3f961cb2e97637a4406019fb31054595 100644 (file)
@@ -10,6 +10,7 @@
 #include <config.h>
 #include <glib.h>
 #include <stdlib.h>
+#include <stdarg.h>
 #include <string.h>
 
 #include <mono/metadata/assembly.h>
@@ -91,8 +92,13 @@ case CEE_##name: {                                                            \
 case CEE_##name: {                                                            \
        ++ip;                                                                 \
        sp -= 2;                                                              \
-       t1 = mono_ctree_new (mp, MB_TERM_LDELEMA, sp [0], sp [1]);            \
-       t1->data.i = s;                                                       \
+        t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);                      \
+        t1->data.i = s;                                                       \
+        t1 = mono_ctree_new (mp, MB_TERM_MUL, sp [1], t1);                    \
+        t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);                      \
+        t2->data.i = G_STRUCT_OFFSET (MonoArray, vector);                     \
+        t2 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t2);                    \
+       t1 = mono_ctree_new (mp, MB_TERM_ADD, t1, t2);                        \
        t1 = mono_ctree_new (mp, op, t1, NULL);                               \
        PUSH_TREE (t1, svt);                                                  \
        break;                                                                \
@@ -106,7 +112,8 @@ case CEE_##name: {                                                            \
        ADD_TREE (t1);                                                        \
        break;                                                                \
 }
-       
+
+/*     
 #define MAKE_STELEM(name, op, s)                                              \
 case CEE_##name: {                                                            \
        ++ip;                                                                 \
@@ -117,6 +124,23 @@ case CEE_##name: {                                                            \
        ADD_TREE (t1);                                                        \
        break;                                                                \
 }
+*/
+
+#define MAKE_STELEM(name, op, s)                                              \
+case CEE_##name: {                                                            \
+       ++ip;                                                                 \
+       sp -= 3;                                                              \
+        t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);                      \
+        t1->data.i = s;                                                       \
+        t1 = mono_ctree_new (mp, MB_TERM_MUL, sp [1], t1);                    \
+        t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);                      \
+        t2->data.i = G_STRUCT_OFFSET (MonoArray, vector);                     \
+        t2 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t2);                    \
+       t1 = mono_ctree_new (mp, MB_TERM_ADD, t1, t2);                        \
+       t1 = mono_ctree_new (mp, op, t1, sp [2]);                             \
+       ADD_TREE (t1);                                                        \
+       break;                                                                \
+}
        
 /* Whether to dump the assembly code after genreating it */
 gboolean mono_jit_dump_asm = FALSE;
@@ -142,6 +166,24 @@ mono_alloc_static0 (int size)
        return g_malloc0 (size);
 } 
 
+static int
+map_store_svt_type (int svt)
+{
+       switch (svt) {
+       case VAL_I32:
+       case VAL_POINTER:
+               return MB_TERM_STIND_I4;
+       case VAL_I64:
+               return MB_TERM_STIND_I8;
+       case VAL_DOUBLE:
+               return MB_TERM_STIND_R8;
+       default:
+               g_assert_not_reached ();
+       }
+
+       return 0;
+}
+
 /**
  * map_stind_type:
  * @type: the type to map
@@ -172,6 +214,7 @@ map_stind_type (MonoType *type)
        case MONO_TYPE_STRING:
        case MONO_TYPE_PTR:
        case MONO_TYPE_SZARRAY:
+       case MONO_TYPE_ARRAY:    
                return MB_TERM_STIND_I4;
        case MONO_TYPE_I8:
        case MONO_TYPE_U8:
@@ -244,6 +287,7 @@ map_ldind_type (MonoType *type, MonoValueType *svt)
        case MONO_TYPE_STRING:
        case MONO_TYPE_PTR:
        case MONO_TYPE_SZARRAY:
+       case MONO_TYPE_ARRAY:    
                *svt = VAL_POINTER;
                return MB_TERM_LDIND_U4;
        case MONO_TYPE_I8:
@@ -525,6 +569,7 @@ ctree_dup_address (MonoMemPool *mp, MBTree *s)
                t->svt = VAL_POINTER;
                return t;
        default:
+               g_warning ("unknown tree opcode %d", s->op);
                g_assert_not_reached ();
        }
 
@@ -542,38 +587,38 @@ mono_store_tree (MonoFlowGraph *cfg, int slot, MBTree *s, MBTree **dup)
        case MB_TERM_STIND_I1:
        case MB_TERM_LDIND_I1:
                t = ctree_dup_address (mp, s->left);
-               t->svt = VAL_I32;
                t = mono_ctree_new (mp, MB_TERM_LDIND_I1, t, NULL);
+               t->svt = VAL_I32;
                break;
        case MB_TERM_STIND_I2:
        case MB_TERM_LDIND_I2:
                t = ctree_dup_address (mp, s->left);
-               t->svt = VAL_I32;
                t = mono_ctree_new (mp, MB_TERM_LDIND_I2, t, NULL);
+               t->svt = VAL_I32;
                break;
        case MB_TERM_STIND_I4:
        case MB_TERM_LDIND_I4:
                t = ctree_dup_address (mp, s->left);
-               t->svt = VAL_I32;
                t = mono_ctree_new (mp, MB_TERM_LDIND_I4, t, NULL);
+               t->svt = VAL_I32;
                break;
        case MB_TERM_STIND_I8:
        case MB_TERM_LDIND_I8:
                t = ctree_dup_address (mp, s->left);
-               t->svt = VAL_I64;
                t = mono_ctree_new (mp, MB_TERM_LDIND_I8, t, NULL);
+               t->svt = VAL_I64;
                break;
        case MB_TERM_STIND_R4:
        case MB_TERM_LDIND_R4:
                t = ctree_dup_address (mp, s->left);
-               t->svt = VAL_DOUBLE;
                t = mono_ctree_new (mp, MB_TERM_LDIND_R4, t, NULL);
+               t->svt = VAL_DOUBLE;
                break;
        case MB_TERM_STIND_R8:
        case MB_TERM_LDIND_R8:
                t = ctree_dup_address (mp, s->left);
-               t->svt = VAL_DOUBLE;
                t = mono_ctree_new (mp, MB_TERM_LDIND_R8, t, NULL);
+               t->svt = VAL_DOUBLE;
                break;
        default: {
                        g_assert (s->svt != VAL_UNKNOWN);
@@ -589,20 +634,8 @@ mono_store_tree (MonoFlowGraph *cfg, int slot, MBTree *s, MBTree **dup)
                        t = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
                        t->data.i = vnum;
                       
-                       switch (s->svt) {
-                       case VAL_I32:
-                       case VAL_POINTER:
-                               t = mono_ctree_new (mp, MB_TERM_STIND_I4, t, s);
-                               break;
-                       case VAL_I64:
-                               t = mono_ctree_new (mp, MB_TERM_STIND_I8, t, s);
-                               break;
-                       case VAL_DOUBLE:
-                               t = mono_ctree_new (mp, MB_TERM_STIND_R8, t, s);
-                               break;
-                       default:
-                               g_assert_not_reached ();
-                       }
+                       t = mono_ctree_new (mp, map_store_svt_type (s->svt), t, s);
+                       t->svt = s->svt;
                }
        }
 
@@ -1055,6 +1088,70 @@ mono_copy_stack (MBTree **sp, int depth, MonoMemPool *mp)
        return NULL;
 }
 
+/**
+ * ves_array_element_address:
+ * @this: a pointer to the array object
+ *
+ * Returns: the address of an array element.
+ */
+static gpointer 
+ves_array_element_address (MonoArray *this, ...)
+{
+       MonoClass *class;
+       va_list ap;
+       int i, ind, esize;
+       gpointer ea;
+
+       g_assert (this != NULL);
+
+       va_start(ap, this);
+
+       class = this->obj.klass;
+
+       ind = va_arg(ap, int) - this->bounds [0].lower_bound;
+       for (i = 1; i < class->rank; i++) {
+               ind = ind*this->bounds [i].length + va_arg(ap, int) -
+                       this->bounds [i].lower_bound;;
+       }
+
+       esize = mono_array_element_size (class);
+       ea = (gpointer*)((char*)this->vector + (ind * esize));
+
+       va_end(ap);
+
+       return ea;
+}
+
+static MonoArray *
+mono_array_new_va (MonoMethod *cm, ...)
+{
+       va_list ap;
+       guint32 *lengths;
+       guint32 *lower_bounds;
+       int pcount = cm->signature->param_count;
+       int rank = cm->klass->rank;
+       int i, d;
+
+       va_start (ap, cm);
+
+       lengths = alloca (sizeof (guint32) * pcount);
+       for (i = 0; i < pcount; ++i)
+               lengths [i] = d = va_arg(ap, int);
+
+       if (rank == pcount) {
+               /* Only lengths provided. */
+               lower_bounds = NULL;
+       } else {
+               g_assert (pcount == (rank * 2));
+               /* lower bounds are first. */
+               lower_bounds = lengths;
+               lengths += rank;
+       }
+       va_end(ap);
+
+       return mono_array_new_full (cm->klass, lengths, lower_bounds);
+}
+
 #define ADD_TREE(t)     do { g_ptr_array_add (forest, (t)); } while (0)
 #define PUSH_TREE(t,k)  do { *sp = t; sp++; t->svt = k; } while (0)
 
@@ -1089,7 +1186,7 @@ mono_analyze_stack (MonoFlowGraph *cfg)
        MonoMethodSignature *signature;
        MonoImage *image;
        MonoValueType svt;
-       MBTree **sp, **stack, *t1, *t2;
+       MBTree **sp, **stack, **arg_sp, *t1, *t2;
        register const unsigned char *ip, *end;
        GPtrArray *forest;
        int i, j, depth, repeat_count;
@@ -1498,16 +1595,13 @@ mono_analyze_stack (MonoFlowGraph *cfg)
 
                        break;
                }
-               case CEE_NEWOBJ:
-               case CEE_CALL: 
-               case CEE_CALLVIRT: {
+               case CEE_NEWOBJ: {
                        MonoMethodSignature *csig;
                        MonoMethod *cm;
-                       MBTree *nobj, *this = NULL;
+                       MBTree *this = NULL;
                        guint32 token;
-                       int i, nargs, align, size, args_size = 0;
-                       int virtual = *ip == CEE_CALLVIRT;
-                       int newobj = *ip == CEE_NEWOBJ;
+                       int i, align, size, args_size = 0;
+                       int newarr = FALSE;
 
                        ++ip;
                        token = read32 (ip);
@@ -1515,114 +1609,208 @@ mono_analyze_stack (MonoFlowGraph *cfg)
 
                        cm = mono_get_method (image, token, NULL);
                        g_assert (cm);
+                       g_assert (!strcmp (cm->name, ".ctor"));
                        
-                       if ((cm->flags & METHOD_ATTRIBUTE_FINAL) ||
-                           !(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
-                               virtual = 0;
-
-                       // fixme: virtual does not work
-                       //virtual = 0;
-
                        csig = cm->signature;
                        g_assert (csig->call_convention == MONO_CALL_DEFAULT);
+                       g_assert (csig->hasthis);
+                       
+                       arg_sp = sp -= csig->param_count;
 
-                       if (newobj) {
-                               int n;
+                       if (cm->klass->parent == mono_defaults.array_class) {
+
+                               newarr = TRUE;
+                               this = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
+                               this->data.p = cm;
 
-                               for (i = 0; i < csig->param_count; i++)
-                                       sp [-i] = sp [-i - 1];
-                               
-                               n = arch_allocate_var (cfg, sizeof (gpointer), sizeof (gpointer), 
-                                                      MONO_TEMPVAR, VAL_UNKNOWN);
-                               
-                               nobj = mono_ctree_new_leaf (mp, MB_TERM_NEWOBJ);
-                               nobj->data.p = cm->klass;
-                               nobj->svt = VAL_POINTER;
-
-                               nobj = ctree_create_store (mp, MB_TERM_ADDR_L, nobj, 
-                                                          &cm->klass->this_arg, (gpointer)n);
-                               ADD_TREE (nobj);
-                               sp [-i] =  ctree_create_dup (mp, nobj);
-                               sp++;
-                       } 
-                       
-                       nargs = csig->param_count;
-                       if (csig->hasthis || virtual || newobj) {
-                               nargs++;
-                               sp = sp - nargs;
-                               this =  *sp;
                        } else {
-                               sp = sp - nargs;
+                               
+                               this = mono_ctree_new_leaf (mp, MB_TERM_NEWOBJ);
+                               this->data.p = cm->klass;
+                               this->svt = VAL_POINTER;
+
+                               t1 = mono_store_tree (cfg, -1, this, &this);
+                               ADD_TREE (t1);
+
                        }
 
-                       //printf ("MINFO %s.%s::%s %d %d\n", cm->klass->name_space, 
-                       //cm->klass->name, cm->name, cm->flags & METHOD_ATTRIBUTE_VIRTUAL, virtual);
-                       if (virtual) {
-                               t2 = ctree_create_dup (mp, this);
-                              
-                               if (!cm->klass->metadata_inited)
-                                       mono_class_metadata_init (cm->klass);
+                       for (i = csig->param_count - 1; i >= 0; i--) {
+                               t1 = mono_ctree_new (mp, MB_TERM_ARG, arg_sp [i], NULL);        
+                               ADD_TREE (t1);
+                               size = mono_type_size (cm->signature->params [i], &align);
+                               args_size += (size + 3) & ~3;
+                       }
+
+                       t1 = mono_ctree_new (mp, MB_TERM_ARG, this, NULL);      
+                       ADD_TREE (t1);
+                       args_size += sizeof (gpointer);
+
+                       if (newarr) {
+
+                               t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
+                               t2->data.p = mono_array_new_va;
+
+                               t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, t2, NULL);
+                               t1->data.i = args_size;
+                               t1->svt = VAL_I32;
 
-                               if (cm->klass->flags & TYPE_ATTRIBUTE_INTERFACE)
-                                       t2 = mono_ctree_new (mp, MB_TERM_INTF_ADDR, t2, NULL);
-                               else 
-                                       t2 = mono_ctree_new (mp, MB_TERM_VFUNC_ADDR, t2, NULL);
-        
-                               t2->data.m = cm;
                        } else {
+                               
                                if (!cm->addr)
                                        cm->addr = arch_create_simple_jit_trampoline (cm);
 
                                t2 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
                                t2->data.p = (char *)cm + G_STRUCT_OFFSET (MonoMethod, addr);
+                               t2 = mono_ctree_new (mp, MB_TERM_LDIND_I4, t2, NULL);
+                       }
+
+                       t1 = mono_ctree_new (mp, map_call_type (csig->ret, &svt), t2, NULL);
+                       t1->data.i = args_size;
+                       t1->svt = svt;
 
+                       if (newarr) {
+                               
+                               t1 = mono_store_tree (cfg, -1, t1, &t2);
+                               ADD_TREE (t1);
+                               PUSH_TREE (t2, t2->svt);
+
+                       } else {
+
+                               ADD_TREE (t1);                  
+                               t1 = ctree_create_dup (mp, this);               
+                               PUSH_TREE (t1, t1->svt);
                        }
+                       break;
+               }
+               case CEE_CALL: 
+               case CEE_CALLVIRT: {
+                       MonoMethodSignature *csig;
+                       MonoMethod *cm;
+                       MBTree *this = NULL;
+                       guint32 token;
+                       int i, align, size, args_size = 0;
+                       int virtual = *ip == CEE_CALLVIRT;
+                       gboolean array_set = FALSE;
+                       gboolean array_get = FALSE;
+                       int nargs;
 
-                       if (nargs) {
+                       ++ip;
+                       token = read32 (ip);
+                       ip += 4;
 
-#ifdef ARCH_ARGS_RIGHT_TO_LEFT
-                               for (i = nargs - 1; i >= 0; i--) {
-#else
-                               for (i = 0; i < nargs; i++) {
-#endif
-                                       t1 = mono_ctree_new (mp, MB_TERM_ARG, sp [i], NULL);    
-                                       ADD_TREE (t1);
+                       cm = mono_get_method (image, token, NULL);
+                       g_assert (cm);
+                       
+                       if ((cm->flags & METHOD_ATTRIBUTE_FINAL) ||
+                           !(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
+                               virtual = 0;
 
-                                       if (!i && this)
-                                               size = mono_type_size (&cm->klass->this_arg, &align);
-                                       else
-                                               size = mono_type_size (cm->signature->params [i - (this != NULL)], &align);
+                       csig = cm->signature;
+                       g_assert (csig->call_convention == MONO_CALL_DEFAULT);
+                       g_assert (!virtual || csig->hasthis);
 
-                                       // fixme: does this really work ?
-                                       args_size += (size + 3) & ~3;
-                               }
+                       nargs = csig->param_count;
+                       arg_sp = sp -= nargs;
+                       
+                       if ((cm->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
+                           (cm->klass->parent == mono_defaults.array_class)) {
+                               if (!strcmp (cm->name, "Set")) { 
+                                       array_set = TRUE;
+                                       nargs--;
+                               } else if (!strcmp (cm->name, "Get")) 
+                                       array_get = TRUE;
                        }
 
-                       t1 = mono_ctree_new (mp, map_call_type (csig->ret, &svt), t2, NULL);
-                       t1->data.i = args_size;
-                       t1->svt = svt;
+                       for (i = nargs - 1; i >= 0; i--) {
+                               t1 = mono_ctree_new (mp, MB_TERM_ARG, arg_sp [i], NULL);        
+                               ADD_TREE (t1);
+                               size = mono_type_size (cm->signature->params [i], &align);
+                               args_size += (size + 3) & ~3;
+                       }
 
-                       if (csig->ret->type != MONO_TYPE_VOID) {
-                               int n;
+                       if (csig->hasthis) {
+                               this = *(--sp);
+                               t1 = mono_ctree_new (mp, MB_TERM_ARG, this, NULL);      
+                               ADD_TREE (t1);
+                               args_size += sizeof (gpointer);
+                       }
 
-                               size = mono_type_size (csig->ret, &align);
-                               n = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, VAL_UNKNOWN);
+                       if (array_get) {
+                               int size, align, vnum;
                                
-                               t2 = ctree_create_store (mp, MB_TERM_ADDR_L, t1, csig->ret, (gpointer)n);
-                               ADD_TREE (t2);
+                               t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
+                               t2->data.p = ves_array_element_address;
 
-                               t1 = ctree_create_dup (mp, t2);
-                               PUSH_TREE (t1, svt);
+                               t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, t2, NULL);
+                               t1->data.i = args_size;
+
+                               t1 = mono_ctree_new (mp, map_ldind_type (csig->ret, &svt), t1, NULL);
+                               t1->svt = svt;          
+
+                               mono_get_val_sizes (t1->svt, &size, &align);
+                               vnum = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, svt);
+
+                               t2 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
+                               t2->data.i = vnum;
+                               t1 = mono_ctree_new (mp, map_store_svt_type (svt), t2, t1);
+                               t1->svt = svt;
+
+                               ADD_TREE (t1);
+                               t1 = ctree_create_dup (mp, t1);
+                               PUSH_TREE (t1, t1->svt);
+
+                       } else if (array_set) {
+
+                               t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
+                               t2->data.p = ves_array_element_address;
+
+                               t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, t2, NULL);
+                               t1->data.i = args_size;
+
+                               t1 = mono_ctree_new (mp, map_stind_type (csig->params [nargs]), t1, arg_sp [nargs]);
+                               ADD_TREE (t1);
+                       
                        } else {
-                               if (newobj) {
-                                       ADD_TREE (t1);                  
-                                       t1 = ctree_create_dup (mp, nobj);               
-                                       PUSH_TREE (t1, t1->svt);
+
+                               if (virtual) {
+                               
+                                       t2 = ctree_create_dup (mp, this);
+                              
+                                       if (!cm->klass->metadata_inited)
+                                               mono_class_metadata_init (cm->klass);
+
+                                       if (cm->klass->flags & TYPE_ATTRIBUTE_INTERFACE)
+                                               t2 = mono_ctree_new (mp, MB_TERM_INTF_ADDR, t2, NULL);
+                                       else 
+                                               t2 = mono_ctree_new (mp, MB_TERM_VFUNC_ADDR, t2, NULL);
+        
+                                       t2->data.m = cm;
+
                                } else {
-                                       ADD_TREE (t1);
+                               
+                                       if (!cm->addr)
+                                               cm->addr = arch_create_simple_jit_trampoline (cm);
+                               
+                                       t2 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
+                                       t2->data.p = (char *)cm + G_STRUCT_OFFSET (MonoMethod, addr);
+                                       t2 = mono_ctree_new (mp, MB_TERM_LDIND_I4, t2, NULL);
                                }
+
+                               t1 = mono_ctree_new (mp, map_call_type (csig->ret, &svt), t2, NULL);
+                               t1->data.i = args_size;
+                               t1->svt = svt;
+
+                               if (csig->ret->type != MONO_TYPE_VOID) {
+
+                                       t1 = mono_store_tree (cfg, -1, t1, &t2);
+                                       ADD_TREE (t1);
+                                       PUSH_TREE (t2, t2->svt);
+                                       
+                               } else
+                                       ADD_TREE (t1);
+   
                        }
+
                        break;
                }
                case CEE_ISINST:
@@ -2092,7 +2280,21 @@ mono_analyze_stack (MonoFlowGraph *cfg)
 
        } while (repeat);
 
-               //printf ("FINISHED\n");
+       //printf ("FINISHED\n");
+}
+
+/* this function is never called */
+static void 
+ves_array_set (MonoArray *this, ...)
+{
+       g_assert_not_reached ();
+}
+
+/* this function is never called */
+static void 
+ves_array_get (MonoArray *this, ...)
+{
+       g_assert_not_reached ();
 }
        
 /**
@@ -2212,6 +2414,8 @@ main (int argc, char *argv [])
 
        mono_init ();
        mono_init_icall ();
+       mono_add_internal_call ("__array_Set", ves_array_set);
+       mono_add_internal_call ("__array_Get", ves_array_get);
 
        assembly = mono_assembly_open (file, NULL, NULL);
        if (!assembly){
index 661a24764eef045f561391c082a18a6d7d8eec1f..7ffd9b5b3f961cb2e97637a4406019fb31054595 100644 (file)
@@ -10,6 +10,7 @@
 #include <config.h>
 #include <glib.h>
 #include <stdlib.h>
+#include <stdarg.h>
 #include <string.h>
 
 #include <mono/metadata/assembly.h>
@@ -91,8 +92,13 @@ case CEE_##name: {                                                            \
 case CEE_##name: {                                                            \
        ++ip;                                                                 \
        sp -= 2;                                                              \
-       t1 = mono_ctree_new (mp, MB_TERM_LDELEMA, sp [0], sp [1]);            \
-       t1->data.i = s;                                                       \
+        t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);                      \
+        t1->data.i = s;                                                       \
+        t1 = mono_ctree_new (mp, MB_TERM_MUL, sp [1], t1);                    \
+        t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);                      \
+        t2->data.i = G_STRUCT_OFFSET (MonoArray, vector);                     \
+        t2 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t2);                    \
+       t1 = mono_ctree_new (mp, MB_TERM_ADD, t1, t2);                        \
        t1 = mono_ctree_new (mp, op, t1, NULL);                               \
        PUSH_TREE (t1, svt);                                                  \
        break;                                                                \
@@ -106,7 +112,8 @@ case CEE_##name: {                                                            \
        ADD_TREE (t1);                                                        \
        break;                                                                \
 }
-       
+
+/*     
 #define MAKE_STELEM(name, op, s)                                              \
 case CEE_##name: {                                                            \
        ++ip;                                                                 \
@@ -117,6 +124,23 @@ case CEE_##name: {                                                            \
        ADD_TREE (t1);                                                        \
        break;                                                                \
 }
+*/
+
+#define MAKE_STELEM(name, op, s)                                              \
+case CEE_##name: {                                                            \
+       ++ip;                                                                 \
+       sp -= 3;                                                              \
+        t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);                      \
+        t1->data.i = s;                                                       \
+        t1 = mono_ctree_new (mp, MB_TERM_MUL, sp [1], t1);                    \
+        t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);                      \
+        t2->data.i = G_STRUCT_OFFSET (MonoArray, vector);                     \
+        t2 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t2);                    \
+       t1 = mono_ctree_new (mp, MB_TERM_ADD, t1, t2);                        \
+       t1 = mono_ctree_new (mp, op, t1, sp [2]);                             \
+       ADD_TREE (t1);                                                        \
+       break;                                                                \
+}
        
 /* Whether to dump the assembly code after genreating it */
 gboolean mono_jit_dump_asm = FALSE;
@@ -142,6 +166,24 @@ mono_alloc_static0 (int size)
        return g_malloc0 (size);
 } 
 
+static int
+map_store_svt_type (int svt)
+{
+       switch (svt) {
+       case VAL_I32:
+       case VAL_POINTER:
+               return MB_TERM_STIND_I4;
+       case VAL_I64:
+               return MB_TERM_STIND_I8;
+       case VAL_DOUBLE:
+               return MB_TERM_STIND_R8;
+       default:
+               g_assert_not_reached ();
+       }
+
+       return 0;
+}
+
 /**
  * map_stind_type:
  * @type: the type to map
@@ -172,6 +214,7 @@ map_stind_type (MonoType *type)
        case MONO_TYPE_STRING:
        case MONO_TYPE_PTR:
        case MONO_TYPE_SZARRAY:
+       case MONO_TYPE_ARRAY:    
                return MB_TERM_STIND_I4;
        case MONO_TYPE_I8:
        case MONO_TYPE_U8:
@@ -244,6 +287,7 @@ map_ldind_type (MonoType *type, MonoValueType *svt)
        case MONO_TYPE_STRING:
        case MONO_TYPE_PTR:
        case MONO_TYPE_SZARRAY:
+       case MONO_TYPE_ARRAY:    
                *svt = VAL_POINTER;
                return MB_TERM_LDIND_U4;
        case MONO_TYPE_I8:
@@ -525,6 +569,7 @@ ctree_dup_address (MonoMemPool *mp, MBTree *s)
                t->svt = VAL_POINTER;
                return t;
        default:
+               g_warning ("unknown tree opcode %d", s->op);
                g_assert_not_reached ();
        }
 
@@ -542,38 +587,38 @@ mono_store_tree (MonoFlowGraph *cfg, int slot, MBTree *s, MBTree **dup)
        case MB_TERM_STIND_I1:
        case MB_TERM_LDIND_I1:
                t = ctree_dup_address (mp, s->left);
-               t->svt = VAL_I32;
                t = mono_ctree_new (mp, MB_TERM_LDIND_I1, t, NULL);
+               t->svt = VAL_I32;
                break;
        case MB_TERM_STIND_I2:
        case MB_TERM_LDIND_I2:
                t = ctree_dup_address (mp, s->left);
-               t->svt = VAL_I32;
                t = mono_ctree_new (mp, MB_TERM_LDIND_I2, t, NULL);
+               t->svt = VAL_I32;
                break;
        case MB_TERM_STIND_I4:
        case MB_TERM_LDIND_I4:
                t = ctree_dup_address (mp, s->left);
-               t->svt = VAL_I32;
                t = mono_ctree_new (mp, MB_TERM_LDIND_I4, t, NULL);
+               t->svt = VAL_I32;
                break;
        case MB_TERM_STIND_I8:
        case MB_TERM_LDIND_I8:
                t = ctree_dup_address (mp, s->left);
-               t->svt = VAL_I64;
                t = mono_ctree_new (mp, MB_TERM_LDIND_I8, t, NULL);
+               t->svt = VAL_I64;
                break;
        case MB_TERM_STIND_R4:
        case MB_TERM_LDIND_R4:
                t = ctree_dup_address (mp, s->left);
-               t->svt = VAL_DOUBLE;
                t = mono_ctree_new (mp, MB_TERM_LDIND_R4, t, NULL);
+               t->svt = VAL_DOUBLE;
                break;
        case MB_TERM_STIND_R8:
        case MB_TERM_LDIND_R8:
                t = ctree_dup_address (mp, s->left);
-               t->svt = VAL_DOUBLE;
                t = mono_ctree_new (mp, MB_TERM_LDIND_R8, t, NULL);
+               t->svt = VAL_DOUBLE;
                break;
        default: {
                        g_assert (s->svt != VAL_UNKNOWN);
@@ -589,20 +634,8 @@ mono_store_tree (MonoFlowGraph *cfg, int slot, MBTree *s, MBTree **dup)
                        t = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
                        t->data.i = vnum;
                       
-                       switch (s->svt) {
-                       case VAL_I32:
-                       case VAL_POINTER:
-                               t = mono_ctree_new (mp, MB_TERM_STIND_I4, t, s);
-                               break;
-                       case VAL_I64:
-                               t = mono_ctree_new (mp, MB_TERM_STIND_I8, t, s);
-                               break;
-                       case VAL_DOUBLE:
-                               t = mono_ctree_new (mp, MB_TERM_STIND_R8, t, s);
-                               break;
-                       default:
-                               g_assert_not_reached ();
-                       }
+                       t = mono_ctree_new (mp, map_store_svt_type (s->svt), t, s);
+                       t->svt = s->svt;
                }
        }
 
@@ -1055,6 +1088,70 @@ mono_copy_stack (MBTree **sp, int depth, MonoMemPool *mp)
        return NULL;
 }
 
+/**
+ * ves_array_element_address:
+ * @this: a pointer to the array object
+ *
+ * Returns: the address of an array element.
+ */
+static gpointer 
+ves_array_element_address (MonoArray *this, ...)
+{
+       MonoClass *class;
+       va_list ap;
+       int i, ind, esize;
+       gpointer ea;
+
+       g_assert (this != NULL);
+
+       va_start(ap, this);
+
+       class = this->obj.klass;
+
+       ind = va_arg(ap, int) - this->bounds [0].lower_bound;
+       for (i = 1; i < class->rank; i++) {
+               ind = ind*this->bounds [i].length + va_arg(ap, int) -
+                       this->bounds [i].lower_bound;;
+       }
+
+       esize = mono_array_element_size (class);
+       ea = (gpointer*)((char*)this->vector + (ind * esize));
+
+       va_end(ap);
+
+       return ea;
+}
+
+static MonoArray *
+mono_array_new_va (MonoMethod *cm, ...)
+{
+       va_list ap;
+       guint32 *lengths;
+       guint32 *lower_bounds;
+       int pcount = cm->signature->param_count;
+       int rank = cm->klass->rank;
+       int i, d;
+
+       va_start (ap, cm);
+
+       lengths = alloca (sizeof (guint32) * pcount);
+       for (i = 0; i < pcount; ++i)
+               lengths [i] = d = va_arg(ap, int);
+
+       if (rank == pcount) {
+               /* Only lengths provided. */
+               lower_bounds = NULL;
+       } else {
+               g_assert (pcount == (rank * 2));
+               /* lower bounds are first. */
+               lower_bounds = lengths;
+               lengths += rank;
+       }
+       va_end(ap);
+
+       return mono_array_new_full (cm->klass, lengths, lower_bounds);
+}
+
 #define ADD_TREE(t)     do { g_ptr_array_add (forest, (t)); } while (0)
 #define PUSH_TREE(t,k)  do { *sp = t; sp++; t->svt = k; } while (0)
 
@@ -1089,7 +1186,7 @@ mono_analyze_stack (MonoFlowGraph *cfg)
        MonoMethodSignature *signature;
        MonoImage *image;
        MonoValueType svt;
-       MBTree **sp, **stack, *t1, *t2;
+       MBTree **sp, **stack, **arg_sp, *t1, *t2;
        register const unsigned char *ip, *end;
        GPtrArray *forest;
        int i, j, depth, repeat_count;
@@ -1498,16 +1595,13 @@ mono_analyze_stack (MonoFlowGraph *cfg)
 
                        break;
                }
-               case CEE_NEWOBJ:
-               case CEE_CALL: 
-               case CEE_CALLVIRT: {
+               case CEE_NEWOBJ: {
                        MonoMethodSignature *csig;
                        MonoMethod *cm;
-                       MBTree *nobj, *this = NULL;
+                       MBTree *this = NULL;
                        guint32 token;
-                       int i, nargs, align, size, args_size = 0;
-                       int virtual = *ip == CEE_CALLVIRT;
-                       int newobj = *ip == CEE_NEWOBJ;
+                       int i, align, size, args_size = 0;
+                       int newarr = FALSE;
 
                        ++ip;
                        token = read32 (ip);
@@ -1515,114 +1609,208 @@ mono_analyze_stack (MonoFlowGraph *cfg)
 
                        cm = mono_get_method (image, token, NULL);
                        g_assert (cm);
+                       g_assert (!strcmp (cm->name, ".ctor"));
                        
-                       if ((cm->flags & METHOD_ATTRIBUTE_FINAL) ||
-                           !(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
-                               virtual = 0;
-
-                       // fixme: virtual does not work
-                       //virtual = 0;
-
                        csig = cm->signature;
                        g_assert (csig->call_convention == MONO_CALL_DEFAULT);
+                       g_assert (csig->hasthis);
+                       
+                       arg_sp = sp -= csig->param_count;
 
-                       if (newobj) {
-                               int n;
+                       if (cm->klass->parent == mono_defaults.array_class) {
+
+                               newarr = TRUE;
+                               this = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
+                               this->data.p = cm;
 
-                               for (i = 0; i < csig->param_count; i++)
-                                       sp [-i] = sp [-i - 1];
-                               
-                               n = arch_allocate_var (cfg, sizeof (gpointer), sizeof (gpointer), 
-                                                      MONO_TEMPVAR, VAL_UNKNOWN);
-                               
-                               nobj = mono_ctree_new_leaf (mp, MB_TERM_NEWOBJ);
-                               nobj->data.p = cm->klass;
-                               nobj->svt = VAL_POINTER;
-
-                               nobj = ctree_create_store (mp, MB_TERM_ADDR_L, nobj, 
-                                                          &cm->klass->this_arg, (gpointer)n);
-                               ADD_TREE (nobj);
-                               sp [-i] =  ctree_create_dup (mp, nobj);
-                               sp++;
-                       } 
-                       
-                       nargs = csig->param_count;
-                       if (csig->hasthis || virtual || newobj) {
-                               nargs++;
-                               sp = sp - nargs;
-                               this =  *sp;
                        } else {
-                               sp = sp - nargs;
+                               
+                               this = mono_ctree_new_leaf (mp, MB_TERM_NEWOBJ);
+                               this->data.p = cm->klass;
+                               this->svt = VAL_POINTER;
+
+                               t1 = mono_store_tree (cfg, -1, this, &this);
+                               ADD_TREE (t1);
+
                        }
 
-                       //printf ("MINFO %s.%s::%s %d %d\n", cm->klass->name_space, 
-                       //cm->klass->name, cm->name, cm->flags & METHOD_ATTRIBUTE_VIRTUAL, virtual);
-                       if (virtual) {
-                               t2 = ctree_create_dup (mp, this);
-                              
-                               if (!cm->klass->metadata_inited)
-                                       mono_class_metadata_init (cm->klass);
+                       for (i = csig->param_count - 1; i >= 0; i--) {
+                               t1 = mono_ctree_new (mp, MB_TERM_ARG, arg_sp [i], NULL);        
+                               ADD_TREE (t1);
+                               size = mono_type_size (cm->signature->params [i], &align);
+                               args_size += (size + 3) & ~3;
+                       }
+
+                       t1 = mono_ctree_new (mp, MB_TERM_ARG, this, NULL);      
+                       ADD_TREE (t1);
+                       args_size += sizeof (gpointer);
+
+                       if (newarr) {
+
+                               t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
+                               t2->data.p = mono_array_new_va;
+
+                               t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, t2, NULL);
+                               t1->data.i = args_size;
+                               t1->svt = VAL_I32;
 
-                               if (cm->klass->flags & TYPE_ATTRIBUTE_INTERFACE)
-                                       t2 = mono_ctree_new (mp, MB_TERM_INTF_ADDR, t2, NULL);
-                               else 
-                                       t2 = mono_ctree_new (mp, MB_TERM_VFUNC_ADDR, t2, NULL);
-        
-                               t2->data.m = cm;
                        } else {
+                               
                                if (!cm->addr)
                                        cm->addr = arch_create_simple_jit_trampoline (cm);
 
                                t2 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
                                t2->data.p = (char *)cm + G_STRUCT_OFFSET (MonoMethod, addr);
+                               t2 = mono_ctree_new (mp, MB_TERM_LDIND_I4, t2, NULL);
+                       }
+
+                       t1 = mono_ctree_new (mp, map_call_type (csig->ret, &svt), t2, NULL);
+                       t1->data.i = args_size;
+                       t1->svt = svt;
 
+                       if (newarr) {
+                               
+                               t1 = mono_store_tree (cfg, -1, t1, &t2);
+                               ADD_TREE (t1);
+                               PUSH_TREE (t2, t2->svt);
+
+                       } else {
+
+                               ADD_TREE (t1);                  
+                               t1 = ctree_create_dup (mp, this);               
+                               PUSH_TREE (t1, t1->svt);
                        }
+                       break;
+               }
+               case CEE_CALL: 
+               case CEE_CALLVIRT: {
+                       MonoMethodSignature *csig;
+                       MonoMethod *cm;
+                       MBTree *this = NULL;
+                       guint32 token;
+                       int i, align, size, args_size = 0;
+                       int virtual = *ip == CEE_CALLVIRT;
+                       gboolean array_set = FALSE;
+                       gboolean array_get = FALSE;
+                       int nargs;
 
-                       if (nargs) {
+                       ++ip;
+                       token = read32 (ip);
+                       ip += 4;
 
-#ifdef ARCH_ARGS_RIGHT_TO_LEFT
-                               for (i = nargs - 1; i >= 0; i--) {
-#else
-                               for (i = 0; i < nargs; i++) {
-#endif
-                                       t1 = mono_ctree_new (mp, MB_TERM_ARG, sp [i], NULL);    
-                                       ADD_TREE (t1);
+                       cm = mono_get_method (image, token, NULL);
+                       g_assert (cm);
+                       
+                       if ((cm->flags & METHOD_ATTRIBUTE_FINAL) ||
+                           !(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
+                               virtual = 0;
 
-                                       if (!i && this)
-                                               size = mono_type_size (&cm->klass->this_arg, &align);
-                                       else
-                                               size = mono_type_size (cm->signature->params [i - (this != NULL)], &align);
+                       csig = cm->signature;
+                       g_assert (csig->call_convention == MONO_CALL_DEFAULT);
+                       g_assert (!virtual || csig->hasthis);
 
-                                       // fixme: does this really work ?
-                                       args_size += (size + 3) & ~3;
-                               }
+                       nargs = csig->param_count;
+                       arg_sp = sp -= nargs;
+                       
+                       if ((cm->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
+                           (cm->klass->parent == mono_defaults.array_class)) {
+                               if (!strcmp (cm->name, "Set")) { 
+                                       array_set = TRUE;
+                                       nargs--;
+                               } else if (!strcmp (cm->name, "Get")) 
+                                       array_get = TRUE;
                        }
 
-                       t1 = mono_ctree_new (mp, map_call_type (csig->ret, &svt), t2, NULL);
-                       t1->data.i = args_size;
-                       t1->svt = svt;
+                       for (i = nargs - 1; i >= 0; i--) {
+                               t1 = mono_ctree_new (mp, MB_TERM_ARG, arg_sp [i], NULL);        
+                               ADD_TREE (t1);
+                               size = mono_type_size (cm->signature->params [i], &align);
+                               args_size += (size + 3) & ~3;
+                       }
 
-                       if (csig->ret->type != MONO_TYPE_VOID) {
-                               int n;
+                       if (csig->hasthis) {
+                               this = *(--sp);
+                               t1 = mono_ctree_new (mp, MB_TERM_ARG, this, NULL);      
+                               ADD_TREE (t1);
+                               args_size += sizeof (gpointer);
+                       }
 
-                               size = mono_type_size (csig->ret, &align);
-                               n = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, VAL_UNKNOWN);
+                       if (array_get) {
+                               int size, align, vnum;
                                
-                               t2 = ctree_create_store (mp, MB_TERM_ADDR_L, t1, csig->ret, (gpointer)n);
-                               ADD_TREE (t2);
+                               t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
+                               t2->data.p = ves_array_element_address;
 
-                               t1 = ctree_create_dup (mp, t2);
-                               PUSH_TREE (t1, svt);
+                               t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, t2, NULL);
+                               t1->data.i = args_size;
+
+                               t1 = mono_ctree_new (mp, map_ldind_type (csig->ret, &svt), t1, NULL);
+                               t1->svt = svt;          
+
+                               mono_get_val_sizes (t1->svt, &size, &align);
+                               vnum = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, svt);
+
+                               t2 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
+                               t2->data.i = vnum;
+                               t1 = mono_ctree_new (mp, map_store_svt_type (svt), t2, t1);
+                               t1->svt = svt;
+
+                               ADD_TREE (t1);
+                               t1 = ctree_create_dup (mp, t1);
+                               PUSH_TREE (t1, t1->svt);
+
+                       } else if (array_set) {
+
+                               t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
+                               t2->data.p = ves_array_element_address;
+
+                               t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, t2, NULL);
+                               t1->data.i = args_size;
+
+                               t1 = mono_ctree_new (mp, map_stind_type (csig->params [nargs]), t1, arg_sp [nargs]);
+                               ADD_TREE (t1);
+                       
                        } else {
-                               if (newobj) {
-                                       ADD_TREE (t1);                  
-                                       t1 = ctree_create_dup (mp, nobj);               
-                                       PUSH_TREE (t1, t1->svt);
+
+                               if (virtual) {
+                               
+                                       t2 = ctree_create_dup (mp, this);
+                              
+                                       if (!cm->klass->metadata_inited)
+                                               mono_class_metadata_init (cm->klass);
+
+                                       if (cm->klass->flags & TYPE_ATTRIBUTE_INTERFACE)
+                                               t2 = mono_ctree_new (mp, MB_TERM_INTF_ADDR, t2, NULL);
+                                       else 
+                                               t2 = mono_ctree_new (mp, MB_TERM_VFUNC_ADDR, t2, NULL);
+        
+                                       t2->data.m = cm;
+
                                } else {
-                                       ADD_TREE (t1);
+                               
+                                       if (!cm->addr)
+                                               cm->addr = arch_create_simple_jit_trampoline (cm);
+                               
+                                       t2 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
+                                       t2->data.p = (char *)cm + G_STRUCT_OFFSET (MonoMethod, addr);
+                                       t2 = mono_ctree_new (mp, MB_TERM_LDIND_I4, t2, NULL);
                                }
+
+                               t1 = mono_ctree_new (mp, map_call_type (csig->ret, &svt), t2, NULL);
+                               t1->data.i = args_size;
+                               t1->svt = svt;
+
+                               if (csig->ret->type != MONO_TYPE_VOID) {
+
+                                       t1 = mono_store_tree (cfg, -1, t1, &t2);
+                                       ADD_TREE (t1);
+                                       PUSH_TREE (t2, t2->svt);
+                                       
+                               } else
+                                       ADD_TREE (t1);
+   
                        }
+
                        break;
                }
                case CEE_ISINST:
@@ -2092,7 +2280,21 @@ mono_analyze_stack (MonoFlowGraph *cfg)
 
        } while (repeat);
 
-               //printf ("FINISHED\n");
+       //printf ("FINISHED\n");
+}
+
+/* this function is never called */
+static void 
+ves_array_set (MonoArray *this, ...)
+{
+       g_assert_not_reached ();
+}
+
+/* this function is never called */
+static void 
+ves_array_get (MonoArray *this, ...)
+{
+       g_assert_not_reached ();
 }
        
 /**
@@ -2212,6 +2414,8 @@ main (int argc, char *argv [])
 
        mono_init ();
        mono_init_icall ();
+       mono_add_internal_call ("__array_Set", ves_array_set);
+       mono_add_internal_call ("__array_Get", ves_array_get);
 
        assembly = mono_assembly_open (file, NULL, NULL);
        if (!assembly){
index 7e6ba4e4e5382a91e71d88276f652a69a078eedc..1eb000b9d2db4aeb2d23627e989fe46375737b6c 100644 (file)
@@ -26,8 +26,6 @@
 #define MBCOST_DATA  MonoFlowGraph
 #define MBALLOC_STATE mono_mempool_alloc (data->mp, sizeof (MBState))
 
-#define ARCH_ARGS_RIGHT_TO_LEFT
-
 typedef enum {
        AMImmediate       = 0,  // ptr
        AMBase            = 1,  // V[REG]  
@@ -121,7 +119,7 @@ guint64 mono_llrem_un  (guint64 a, guint64 b);
 %term CEQ
 %term CONV_I4 CONV_I1 CONV_I2 CONV_I8 CONV_R8
 %term INTF_ADDR VFUNC_ADDR NOP BOX NEWARR NEWOBJ POP 
-%term LDLEN LDELEMA
+%term LDLEN
 
 #
 # we start at stmt
@@ -268,6 +266,29 @@ reg: LDIND_I4 (addr) {
        }
 }
 
+reg: LDIND_U4 (addr) {
+       switch (tree->left->data.ainfo.amode) {
+
+       case AMImmediate:
+               x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset, 4);
+               break;
+
+       case AMBase:
+               x86_mov_reg_membase (s->code, tree->reg1, tree->left->data.ainfo.basereg, 
+                                    tree->left->data.ainfo.offset, 4);
+               break;          
+       case AMIndex:
+               x86_mov_reg_memindex (s->code, tree->reg1, X86_NOBASEREG, tree->left->data.ainfo.offset,
+                                     tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift, 4);
+               break;          
+       case AMBaseIndex:
+               x86_mov_reg_memindex (s->code, tree->reg1, tree->left->data.ainfo.basereg, 
+                                     tree->left->data.ainfo.offset, tree->left->data.ainfo.indexreg, 
+                                     tree->left->data.ainfo.shift, 4);
+               break;          
+       }
+}
+
 locaddr: ADDR_L 10 {
        tree->data.i = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).offset;
 }
@@ -493,8 +514,23 @@ reg: SHR_UN (reg, reg) {
 }
 
 reg: BOX (reg) {
-       // fixme: implement me
-       //g_assert_not_reached ();
+       if (tree->reg1 != X86_EAX)
+               x86_push_reg (s->code, X86_EAX);
+       x86_push_reg (s->code, X86_ECX);
+       x86_push_reg (s->code, X86_EDX);
+
+       x86_push_reg (s->code, tree->left->reg1); //save it to memory
+       x86_push_reg (s->code, X86_ESP); // push address to saved value
+       x86_push_imm (s->code, tree->data.p);
+       x86_call_code (s->code, mono_value_box);
+       x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
+
+       x86_pop_reg (s->code, X86_EDX);
+       x86_pop_reg (s->code, X86_ECX);
+       if (tree->reg1 != X86_EAX) {
+               x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
+               x86_pop_reg (s->code, X86_EAX);
+       }
 }
 
 # array support
@@ -505,12 +541,11 @@ reg: LDLEN (reg) {
                             G_STRUCT_OFFSET (MonoArrayBounds, length), 4);
 }
 
-reg: LDELEMA (reg, reg) {
-       x86_mov_reg_membase (s->code, tree->reg1, tree->left->reg1, 
-                            G_STRUCT_OFFSET (MonoArray, vector), 4);
-       x86_imul_reg_reg_imm (s->code, tree->right->reg1, tree->right->reg1, tree->data.i);
-       x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->right->reg1);
-}
+#reg: LDELEMA (reg, reg) {
+#      x86_imul_reg_reg_imm (s->code, tree->right->reg1, tree->right->reg1, tree->data.i);
+#      x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->right->reg1);
+#      x86_alu_reg_imm (s->code, X86_ADD, tree->reg1, G_STRUCT_OFFSET (MonoArray, vector));
+#}
 
 reg: NEWARR (reg) {
        if (tree->reg1 != X86_EAX)
@@ -526,7 +561,7 @@ reg: NEWARR (reg) {
        x86_pop_reg (s->code, X86_EDX);
        x86_pop_reg (s->code, X86_ECX);
        if (tree->reg1 != X86_EAX) {
-               x86_mov_reg_reg (s->code, X86_EAX, tree->reg1, 4);
+               x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
                x86_pop_reg (s->code, X86_EAX);
        }
 }
@@ -544,7 +579,7 @@ reg: NEWOBJ {
        x86_pop_reg (s->code, X86_EDX);
        x86_pop_reg (s->code, X86_ECX);
        if (tree->reg1 != X86_EAX) {
-               x86_mov_reg_reg (s->code, X86_EAX, tree->reg1, 4);
+               x86_mov_reg_reg (s->code, tree->reg1, X86_EAX, 4);
                x86_pop_reg (s->code, X86_EAX);
        }
 }
@@ -828,12 +863,22 @@ stmt: ARG (CONST_I4) "MB_USE_OPT1(0)" {
 
 stmt: ARG (LDIND_OBJ (reg)) {
       // fixme:
-      //g_assert_not_reached ();
+      g_assert_not_reached ();
+}
+
+reg: CALL_I4 (CONST_I4) {
+       
+       x86_call_code (s->code, tree->left->data.p);
+
+       if (tree->data.i)
+               x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.i);
+       
+       g_assert (tree->reg1 == X86_EAX);
 }
 
-reg: CALL_I4 (ADDR_G) {
+reg: CALL_I4 (LDIND_I4 (ADDR_G)) {
        
-       x86_call_mem (s->code, tree->left->data.p);
+       x86_call_mem (s->code, tree->left->left->data.p);
 
        if (tree->data.i)
                x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.i);
@@ -869,8 +914,8 @@ reg: CALL_I4 (VFUNC_ADDR (reg)) {
        g_assert (tree->reg1 == X86_EAX);
 }
 
-stmt: CALL_I4 (ADDR_G) {
-       x86_call_mem (s->code, tree->left->data.p);
+stmt: CALL_I4 (LDIND_I4 (ADDR_G)) {
+       x86_call_mem (s->code, tree->left->left->data.p);
 
        if (tree->data.i)
                x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.i);
@@ -900,13 +945,6 @@ stmt: CALL_I4 (VFUNC_ADDR (reg)) {
                x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.i);
 }
 
-stmt: CALL_I4 (ADDR_G) {
-       x86_call_mem (s->code, tree->left->data.p);
-
-       if (tree->data.i)
-               x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.i);
-}
-
 stmt: SWITCH (reg) {
        guint32 offset;
        guint32 *jt = (guint32 *)tree->data.p;
@@ -1155,19 +1193,9 @@ lreg: REM_UN (lreg, lreg) {
                x86_pop_reg (s->code, X86_ECX);
 }
 
-lreg: CALL_I8 (addr) {
-
-       switch (tree->left->data.ainfo.amode) {
-       case AMImmediate:
-               x86_call_mem (s->code, tree->left->data.ainfo.offset);
-               break;
-       case AMBase:
-               x86_call_membase (s->code, tree->left->data.ainfo.basereg, 
-                                 tree->left->data.ainfo.offset);
-               break;
-       default:
-               g_assert_not_reached ();
-       }
+lreg: CALL_I8 (LDIND_I4 (ADDR_G)) {
+       
+       x86_call_mem (s->code, tree->left->left->data.p);
 
        if (tree->data.i)
                x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.i);
@@ -1416,11 +1444,26 @@ freg: CONV_R8 (reg) {
 }
 
 freg: CONST_R4 {
-       x86_fld (s->code, tree->data.p, FALSE);
+       float f = *(float *)tree->data.p;
+
+       if (f == 0.0)
+               x86_fldz (s->code);
+       else if (f == 1.0)
+               x86_fld1(s->code);
+       else
+               x86_fld (s->code, tree->data.p, FALSE);
 }
 
 freg: CONST_R8 {
-       x86_fld (s->code, tree->data.p, TRUE);
+       double d = *(double *)tree->data.p;
+       printf ("TEST %f\n", d);
+
+       if (d == 0.0)
+               x86_fldz (s->code);
+       else if (d == 1.0)
+               x86_fld1(s->code);
+       else
+               x86_fld (s->code, tree->data.p, TRUE);
 }
 
 freg: LDIND_R4 (locaddr) {
@@ -1493,21 +1536,31 @@ stmt: BNE_UN (freg, freg) {
        x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
        x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x4000);
        offset = 6 + s->code - s->start;
-       x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, TRUE);
+       x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, FALSE);
 }
 
-stmt: BLT_UN (freg, freg) {
+stmt: BLT (freg, freg) {
        gint32 offset;
 
        tree->is_jump = 1;
        x86_fcompp (s->code);
        x86_fnstsw (s->code);
        x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
-       x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
        offset = 6 + s->code - s->start;
        x86_branch32 (s->code, X86_CC_EQ, tree->data.bb->addr - offset, TRUE);
 }
 
+stmt: BLT_UN (freg, freg) {
+       gint32 offset;
+
+       tree->is_jump = 1;
+       x86_fcompp (s->code);
+       x86_fnstsw (s->code);
+       x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
+       offset = 6 + s->code - s->start;
+       x86_branch32 (s->code, X86_CC_EQ, tree->data.bb->addr - offset, FALSE);
+}
+
 stmt: BGE_UN (freg, freg) {
        gint32 offset;
 
@@ -1515,9 +1568,8 @@ stmt: BGE_UN (freg, freg) {
        x86_fcompp (s->code);
        x86_fnstsw (s->code);
        x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
-       x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
        offset = 6 + s->code - s->start;
-       x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, TRUE);
+       x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, FALSE);
 }
 
 stmt: BGT_UN (freg, freg) {
@@ -1527,8 +1579,9 @@ stmt: BGT_UN (freg, freg) {
        x86_fcompp (s->code);
        x86_fnstsw (s->code);
        x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
+       x86_alu_reg_imm (s->code, X86_CMP, X86_EAX, 0x0100);
        offset = 6 + s->code - s->start;
-       x86_branch32 (s->code, X86_CC_EQ, tree->data.bb->addr - offset, TRUE);
+       x86_branch32 (s->code, X86_CC_EQ, tree->data.bb->addr - offset, FALSE);
 }
 
 stmt: BLE_UN (freg, freg) {
@@ -1539,22 +1592,12 @@ stmt: BLE_UN (freg, freg) {
        x86_fnstsw (s->code);
        x86_alu_reg_imm (s->code, X86_AND, X86_EAX, 0x4500);
        offset = 6 + s->code - s->start;
-       x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, TRUE);
+       x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, FALSE);
 }
 
-freg: CALL_R8 (addr) {
-
-       switch (tree->left->data.ainfo.amode) {
-       case AMImmediate:
-               x86_call_mem (s->code, tree->left->data.ainfo.offset);
-               break;
-       case AMBase:
-               x86_call_membase (s->code, tree->left->data.ainfo.basereg, 
-                                 tree->left->data.ainfo.offset);
-               break;
-       default:
-               g_assert_not_reached ();
-       }
+freg: CALL_R8 (LDIND_I4 (ADDR_G)) {
+       
+       x86_call_mem (s->code, tree->left->left->data.p);
 
        if (tree->data.i)
                x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.i);
index 502ae749e9b2c5f0bbdc1c71383d0a474f819882..96b5970fdf6aaee0f7a422424d0d786bb96cede4 100755 (executable)
@@ -97,7 +97,7 @@ public class Test {
        
 
        public static int Main () {
-                      
+
                if (atest () != 0)
                        return 1;