[Mono-list] jit patch: array support

Dietmar Maurer dietmar@ximian.com
09 Nov 2001 11:25:03 +0100


Index: mono/jit/ChangeLog
===================================================================
RCS file: /cvs/public/mono/mono/jit/ChangeLog,v
retrieving revision 1.37
diff -u -r1.37 ChangeLog
--- mono/jit/ChangeLog	2001/11/08 21:38:32	1.37
+++ mono/jit/ChangeLog	2001/11/09 06:26:26
@@ -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 ellements (using base+index+offset
+	adressing mode)
+
 2001-11-07  Miguel de Icaza  <miguel@ximian.com>
 
 	* mempool.c: Include string.h to kill warning.
Index: mono/jit/emit-x86.c
===================================================================
RCS file: /cvs/public/mono/mono/jit/emit-x86.c,v
retrieving revision 1.15
diff -u -r1.15 emit-x86.c
--- mono/jit/emit-x86.c	2001/11/08 21:38:32	1.15
+++ mono/jit/emit-x86.c	2001/11/09 06:26:27
@@ -37,7 +37,7 @@
 	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 @@
 		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 @@
 			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 @@
 	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 @@
 		/* do nothing */
 	}
 
+	//printf ("RALLOC END %d %p\n",  tree->op, rs->free_mask);
 	tree->emit = mono_burg_func [ern];
 }
 
@@ -507,6 +512,7 @@
 			//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 @@
 	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: mono/jit/testjit.c
===================================================================
RCS file: /cvs/public/mono/mono/jit/testjit.c,v
retrieving revision 1.39
diff -u -r1.39 testjit.c
--- mono/jit/testjit.c	2001/11/08 21:38:32	1.39
+++ mono/jit/testjit.c	2001/11/09 06:26:27
@@ -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: {                                                            \
 	++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 @@
 	ADD_TREE (t1);                                                        \
 	break;                                                                \
 }
-	
+
+/*	
 #define MAKE_STELEM(name, op, s)                                              \
 case CEE_##name: {                                                            \
 	++ip;                                                                 \
@@ -117,6 +124,23 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 		t->svt = VAL_POINTER;
 		return t;
 	default:
+		g_warning ("unknown tree opcode %d", s->op);
 		g_assert_not_reached ();
 	}
 
@@ -542,38 +587,38 @@
 	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 @@
 			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 @@
 	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 @@
 	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 @@
 
 			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 @@
 
 			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) {
 
-				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;
+				newarr = TRUE;
+				this = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
+				this->data.p = cm;
+
 			} 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;
+			}
 
-				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;
+			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;
+
 			} 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._rray_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:
@@ -2091,8 +2279,22 @@
 
 
 	} while (repeat);
+
+	//printf ("FINISHED\n");
+}
+
+/* this function is never called */
+static void 
+ves_array_set (MonoArray *this, ...)
+{
+	g_assert_not_reached ();
+}
 
-		//printf ("FINISHED\n");
+/* this function is never called */
+static void 
+ves_array_get (MonoArray *this, ...)
+{
+	g_assert_not_reached ();
 }
 	
 /**
@@ -2212,6 +2414,8 @@
 
 	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: mono/jit/x86.brg
===================================================================
RCS file: /cvs/public/mono/mono/jit/x86.brg,v
retrieving revision 1.32
diff -u -r1.32 x86.brg
--- mono/jit/x86.brg	2001/11/08 21:38:32	1.32
+++ mono/jit/x86.brg	2001/11/09 06:26:27
@@ -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 @@
 %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_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: 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 @@
 			     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 @@
 	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 @@
 	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 (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 @@
 	g_assert (tree->reg1 == X86_EAX);
 }
 
-stmt: CALL_I4 (ADDR_G) {
-	x86_call_mem (s->c_de, 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 @@
 		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 @@
 		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: 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 @@
 	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 @@
 	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 @@
 	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 @@
 	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: mono/tests/array.cs
===================================================================
RCS file: /cvs/public/mono/mono/tests/array.cs,v
retrieving revision 1.5
diff -u -r1.5 array.cs
--- mono/tests/array.cs	2001/08/28 10:47:36	1.5
+++ mono/tests/array.cs	2001/11/09 06:26:27
@@ -97,7 +97,7 @@
 	
 
 	public static int Main () {
-	       	       
+
 		if (atest () != 0)
 			return 1;