[Mono-list] jit patch: LDELEM/STELEM impl.

Dietmar Maurer dietmar@ximian.com
02 Nov 2001 18:27:49 +0100


Index: mono/jit/ChangeLog
===================================================================
RCS file: /cvs/public/mono/mono/jit/ChangeLog,v
retrieving revision 1.31
diff -u -r1.31 ChangeLog
--- mono/jit/ChangeLog	2001/10/15 09:50:03	1.31
+++ mono/jit/ChangeLog	2001/11/02 13:27:16
@@ -1,3 +1,10 @@
+2001-11-02  Dietmar Maurer  <dietmar@ximian.com>
+
+	* testjit.c: impl. STELEM_XX, STELEM_XX
+
+	* x86.brg: impl. LDLEN, LDELEMA
+	
+
 2001-10-15  Dietmar Maurer  <dietmar@ximian.com>
 
 	* x86.brg: added some experimental code for CALL
Index: mono/jit/emit-x86.c
===================================================================
RCS file: /cvs/public/mono/mono/jit/emit-x86.c,v
retrieving revision 1.9
diff -u -r1.9 emit-x86.c
--- mono/jit/emit-x86.c	2001/11/02 10:12:24	1.9
+++ mono/jit/emit-x86.c	2001/11/02 13:27:16
@@ -164,7 +164,7 @@
 			tree->reg1 = X86_EAX;
 			break;
 		case MB_TERM_CALL_I8:
-		case MB_TERM_MUL:
+		//case MB_TERM_MUL:
 			tree->reg1 = X86_EAX;
 			tree->reg2 = X86_EDX;
 			break;
@@ -201,7 +201,7 @@
 	case MB_NTERM_reg:
 		if ((tree->reg1 = 
 		     mono_regset_alloc_reg (rs, tree->reg1, tree->exclude_mask)) == -1) {
-			g_warning ("register allocation failed\n");
+			g_warning ("register allocation failed %d %p %p\n",  tree->reg1, rs->free_mask, tree->exclude_mask);
 			g_assert_not_reached ();
 		}
 
@@ -260,7 +260,9 @@
 
 		for (j = 0; j < top; j++) {
 			MBTree *t1 = (MBTree *) g_ptr_array_index (forest, j);
+			//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);
 		}
 	}
 }
Index: mono/jit/testjit.c
===================================================================
RCS file: /cvs/public/mono/mono/jit/testjit.c,v
retrieving revision 1.33
diff -u -r1.33 testjit.c
--- mono/jit/testjit.c	2001/11/02 10:12:24	1.33
+++ mono/jit/testjit.c	2001/11/02 13:27:16
@@ -86,6 +86,17 @@
 	break;                                                                \
 }
 	
+#define MAKE_LDELEM(name, op, svt, s)                                         \
+case CEE_##name: {                                                            \
+	++ip;                                                                 \
+	sp -= 2;                                                              \
+	t1 = mono_ctree_new (mp, MB_TERM_LDELEMA, sp [0], sp [1]);            \
+	t1->size = s;                                                         \
+	t1 = mono_ctree_new (mp, op, t1, NULL);                               \
+	PUSH_TREE (t1, svt);                                                  \
+	break;                                                                \
+}
+	
 #define MAKE_STIND(name, op)                                                  \
 case CEE_##name: {                                                            \
 	++ip;                                                                 \
@@ -95,6 +106,17 @@
 	break;                                                                \
 }
 	
+#define MAKE_STELEM(name, op, s)                                              \
+case CEE_##name: {                                                            \
+	++ip;                                                                 \
+	sp -= 3;                                                              \
+	t1 = mono_ctree_new (mp, MB_TERM_LDELEMA, sp [0], sp [1]);            \
+	t1->size = s;                                                         \
+	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;
 
@@ -145,6 +167,7 @@
 	case MONO_TYPE_OBJECT:
 	case MONO_TYPE_STRING:
 	case MONO_TYPE_PTR:
+	case MONO_TYPE_SZARRAY:
 		return MB_TERM_STIND_I4;
 	case MONO_TYPE_I8:
 	case MONO_TYPE_U8:
@@ -216,6 +239,7 @@
 	case MONO_TYPE_OBJECT:
 	case MONO_TYPE_STRING:
 	case MONO_TYPE_PTR:
+	case MONO_TYPE_SZARRAY:
 		*svt = VAL_POINTER;
 		return MB_TERM_LDIND_U4;
 	case MONO_TYPE_I8:
@@ -584,26 +608,6 @@
 	return t;
 }
 
-/* fixme: this is to clumsy :-( */
-static MBTree *
-ctree_create_newobj (MonoMemPool *mp, MonoClass *klass)
-{
-	MBTree *t1, *t2;
-	static gpointer newobj_func = mono_object_new;
-
-	t1 = mono_ctree_new_leaf (mp, MB_TERM_ARG_END);
-	t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
-	t2->data.p = klass;
-	t1 = mono_ctree_new (mp, MB_TERM_ARG, t1, t2);	
-
-	t2 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
-	t2->data.p = &newobj_func;
-	t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, t1, t2);
-	t1->size = sizeof (gpointer);
-
-	return t1;
-}
-
 /**
  * Create a duplicate of the value of a tree. This is
  * easy for trees starting with LDIND/STIND, since the
@@ -842,6 +846,26 @@
 		case CEE_STIND_R4:
 		case CEE_STIND_R8:
 		case CEE_STIND_REF:
+		case CEE_STELEM_I:
+		case CEE_STELEM_I1:
+		case CEE_STELEM_I2:
+		case CEE_STELEM_I4:
+		case CEE_STELEM_I8:
+		case CEE_STELEM_R4:
+		case CEE_STELEM_R8:
+		case CEE_STELEM_REF:
+		case CEE_LDLEN:
+		case CEE_LDELEM_I1:
+		case CEE_LDELEM_U1:
+		case CEE_LDELEM_I2:
+		case CEE_LDELEM_U2:
+		case CEE_LDELEM_I4:
+		case CEE_LDELEM_U4:
+		case CEE_LDELEM_I8:
+		case CEE_LDELEM_I:
+		case CEE_LDELEM_R4:
+		case CEE_LDELEM_R8:
+		case CEE_LDELEM_REF:
 			ip++;
 			break;
 		case CEE_RET:
@@ -1194,6 +1218,15 @@
 			PUSH_TREE (t1, VAL_POINTER);
 			break;
 		}
+		case CEE_LDLEN: {
+			ip++;
+			sp--;
+			
+			t1 = mono_ctree_new (mp, MB_TERM_LDLEN, *sp, NULL);
+			PUSH_TREE (t1, VAL_I32);
+			break;
+		}
+
 		case CEE_LDOBJ: {
 			guint32 token;
 			MonoClass *c;
@@ -1448,6 +1481,7 @@
 			ip += 4;
 
 			t1 = mono_ctree_new (mp, MB_TERM_NEWARR, *sp, NULL);
+			t1->data.p = class;
 			PUSH_TREE (t1, VAL_POINTER);
 
 			break;
@@ -1491,8 +1525,11 @@
 				
 				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_newobj (mp, cm->klass);
 				nobj = ctree_create_store (mp, MB_TERM_ADDR_L, nobj, 
 							   &cm->klass->this_arg, (gpointer)n);
 				ADD_TREE (nobj);
@@ -1529,8 +1566,6 @@
 				t2->data.p = (char *)cm + G_STRUCT_OFFSET (MonoMethod, addr);
 			}
 
-			t1 = mono_ctree_new_leaf (mp, MB_TERM_ARG_END);
-
 			if (nargs) {
 
 #ifdef ARCH_ARGS_RIGHT_TO_LEFT
@@ -1538,8 +1573,9 @@
 #else
 				for (i = 0; i < nargs; i++) {
 #endif
-					t1 = mono_ctree_new (mp, MB_TERM_ARG, t1, sp [i]);	
-			
+					t1 = mono_ctree_new (mp, MB_TERM_ARG, sp [i], NULL);	
+					ADD_TREE (t1);
+
 					if (!i && this)
 						size = mono_type_size (&cm->klass->this_arg, &align);
 					else
@@ -1550,7 +1586,7 @@
 				}
 			}
 
-			t1 = mono_ctree_new (mp, map_call_type (csig->ret, &svt), t1, t2);
+			t1 = mono_ctree_new (mp, map_call_type (csig->ret, &svt), t2, NULL);
 			t1->size = args_size;
 			t1->svt = svt;
 
@@ -1747,6 +1783,27 @@
 		MAKE_STIND (STIND_R4,  MB_TERM_STIND_R4)
 		MAKE_STIND (STIND_R8,  MB_TERM_STIND_R8)
 		MAKE_STIND (STIND_REF, MB_TERM_STIND_I4)
+
+		MAKE_LDELEM (LDELEM_I1,  MB_TERM_LDIND_I1, VAL_I32, 1)
+		MAKE_LDELEM (LDELEM_U1,  MB_TERM_LDIND_U1, VAL_I32, 1)
+		MAKE_LDELEM (LDELEM_I2,  MB_TERM_LDIND_I2, VAL_I32, 2)
+		MAKE_LDELEM (LDELEM_U2,  MB_TERM_LDIND_U2, VAL_I32, 2)
+		MAKE_LDELEM (LDELEM_I,   MB_TERM_LDIND_I4, VAL_I32, 4)
+		MAKE_LDELEM (LDELEM_I4,  MB_TERM_LDIND_I4, VAL_I32, 4)
+		MAKE_LDELEM (LDELEM_REF, MB_TERM_LDIND_U4, VAL_I32, 4)
+		MAKE_LDELEM (LDELEM_U4,  MB_TERM_LDIND_U4, VAL_I32, 4)
+		MAKE_LDELEM (LDELEM_I8,  MB_TERM_LDIND_I8, VAL_I64, 8)
+		MAKE_LDELEM (LDELEM_R4,  MB_TERM_LDIND_R4, VAL_DOUBLE, 4)
+		MAKE_LDELEM (LDELEM_R8,  MB_TERM_LDIND_R8, VAL_DOUBLE, 8)
+
+		MAKE_STELEM (STELEM_I1,  MB_TERM_STIND_I1, 1)
+		MAKE_STELEM (STELEM_I2,  MB_TERM_STIND_I2, 2)
+		MAKE_STELEM (STELEM_I4,  MB_TERM_STIND_I4, 4)
+		MAKE_STELEM (STELEM_I,   MB_TERM_STIND_I4, 4)
+		MAKE_STELEM (STELEM_REF, MB_TERM_STIND_I4, 4)
+		M_KE_STELEM (STELEM_I8,  MB_TERM_STIND_I8, 8)
+		MAKE_STELEM (STELEM_R4,  MB_TERM_STIND_R4, 4)
+		MAKE_STELEM (STELEM_R8,  MB_TERM_STIND_R8, 8)
 
 		case CEE_NEG: {
 			ip++;
Index: mono/jit/x86.brg
===================================================================
RCS file: /cvs/public/mono/mono/jit/x86.brg,v
retrieving revision 1.26
diff -u -r1.26 x86.brg
--- mono/jit/x86.brg	2001/11/02 10:12:24	1.26
+++ mono/jit/x86.brg	2001/11/02 13:27:16
@@ -104,13 +104,14 @@
 %term LDIND_I1 LDIND_U1 LDIND_I2 LDIND_U2 LDIND_I4 LDIND_I8 LDIND_R4 LDIND_R8
 %term LDIND_U4 LDIND_OBJ
 %term STIND_I1 STIND_I2 STIND_I4 STIND_I8 STIND_R4 STIND_R8 STIND_OBJ
-%term ADDR_L ADDR_G ARG ARG_END CALL_I4 CALL_I8 CALL_R8
+%term ADDR_L ADDR_G ARG CALL_I4 CALL_I8 CALL_R8
 %term BREAK SWITCH BR RET RETV 
 %term ADD SUB MUL DIV DIV_UN REM REM_UN AND OR XOR SHL SHR SHR_UN NEG NOT
 %term BLT BLT_UN BEQ BNE_UN BRTRUE BRFALSE BGE BGE_UN BLE BLE_UN BGT BGT_UN 
 %term CEQ
 %term CONV_I4 CONV_I1 CONV_I2 CONV_I8 CONV_R8
-%term INTF_ADDR VFUNC_ADDR NOP BOX NEWARR POP
+%term INTF_ADDR VFUNC_ADDR NOP BOX NEWARR NEWOBJ POP 
+%term LDLEN LDELEMA
 
 #
 # we start at stmt
@@ -481,9 +482,53 @@
 	//g_assert_not_reached ();
 }
 
+# array support
+reg: LDLEN (reg) {
+	x86_mov_reg_membase (s->code, tree->reg1, tree->left->reg1,  G_STRUCT_OFFSET (MonoArray, bounds), 4);
+	x86_mov_reg_membase (s->code, tree->reg1, tree->reg1,  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->size);
+	x86_alu_reg_reg (s->code, X86_ADD, tree->reg1, tree->right->reg1);
+}
+
 reg: NEWARR (reg) {
-	// fixme: implement me
+	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);
+	x86_push_imm (s->code, tree->data.p);
+	x86_call_code (s->code, mono_array_new);
+	x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, sizeof (gpointer) + 4);
+
+	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_pop_reg (s->code, X86_EAX);
+	}
+}
 
+reg: NEWOBJ {
+	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_imm (s->code, tree->data.p);
+	x86_call_code (s->code, mono_object_new);
+	x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, sizeof (gpointer));
+
+	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_pop_reg (s->code, X86_EAX);
+	}
 }
 
 stmt: NOP
@@ -750,29 +795,27 @@
 		x86_jump32 (s->code, s->epilog - 5);
 	} 
 }
-
-argl: ARG_END
 
-argl: ARG (argl, reg) {
-	x86_push_reg (s->code, tree->right->reg1);
+stmt: ARG (reg) {
+	x86_push_reg (s->code, tree->left->reg1);
 }
 
-argl: ARG (argl, ADDR_G) {
-	x86_push_imm (s->code, tree->right->data.p);
+stmt: ARG (ADDR_G) {
+	x86_push_imm (s->code, tree->left->data.p);
 }
 
-argl: ARG (argl, CONST_I4) "MB_USE_OPT1(0)" {
-	x86_push_imm (s->code, tree->right->data.i);
+stmt: ARG (CONST_I4) "MB_USE_OPT1(0)" {
+	x86_push_imm (s->code, tree->left->data.i);
 }
 
-argl: ARG (argl, LDIND_OBJ (reg)) {
+stmt: ARG (LDIND_OBJ (reg)) {
       // fixme:
       //g_assert_not_reached ();
 }
 
-reg: CALL_I4 (argl, ADDR_G) {
+reg: CALL_I4 (ADDR_G) {
 	
-	x86_call_mem (s->code, tree->right->data.p);
+	x86_call_mem (s->code, tree->left->data.p);
 
 	if (tree->size)
 		x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->size);
@@ -780,13 +823,13 @@
 	g_assert (tree->reg1 == X86_EAX);
 }
 
-reg: CALL_I4 (argl, INTF_ADDR (reg)) {
-	int reg1 = tree->right->left->reg1;
+reg: CALL_I4 (INTF_ADDR (reg)) {
+	int reg1 = tree->left->left->reg1;
 
 	x86_mov_reg_membase (s->code, reg1, reg1, 0, 4);
 	x86_mov_reg_membase (s->code, reg1, reg1, G_STRUCT_OFFSET (MonoClass, interface_offsets), 4);
-	x86_mov_reg_membase (s->code, reg1, reg1, tree->right->data.i, 4);
-	x86_call_membase (s->code, reg1, tree->right->size);
+	x86_mov_reg_membase (s->code, reg1, reg1, tree->left->data.i, 4);
+	x86_call_membase (s->code, reg1, tree->left->size);
 
 	if (tree->size)
 		x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->size);
@@ -794,11 +837,11 @@
 	g_assert (tree->reg1 == X86_EAX);
 }
 
-reg: CALL_I4 (argl, VFUNC_ADDR (reg)) {
-	int reg1 = tree->right->left->reg1;
+reg: CALL_I4 (VFUNC_ADDR (reg)) {
+	int reg1 = tree->left->left->reg1;
 
 	x86_mov_reg_membase (s->code, reg1, reg1, 0, 4);
-	x86_call_membase (s->code, reg1, G_STRUCT_OFFSET (MonoClass, vtable + tree->right->data.i));
+	x86_call_membase (s->code, reg1, G_STRUCT_OFFSET (MonoClass, vtable + tree->left->data.i));
 
 	if (tree->size)
 		x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->size);
@@ -806,37 +849,37 @@
 	g_assert (tree->reg1 == X86_EAX);
 }
 
-stmt: CALL_I4 (argl, ADDR_G) {
-	x86_call_mem (s->code, tree->right->data.p);
+stmt: CALL_I4 (ADDR_G) {
+	x86_call_mem (s->code, tree->left->data.p);
 
 	if (tree->size)
 		x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->size);
 }
 
-stmt: CALL_I4 (argl, INTF_ADDR (reg)) {
-	int reg1 = tree->right->left->reg1;
+stmt: CALL_I4 (INTF_ADDR (reg)) {
+	int reg1 = tree->left->left->reg1;
 
 	x86_mov_reg_membase (s->code, reg1, reg1, 0, 4);
 	x86_mov_reg_membase (s->code, reg1, reg1, G_STRUCT_OFFSET (MonoClass, interface_offsets), 4);
-	x86_mov_reg_membase (s->code, reg1, reg1, tree->right->data.i, 4);
-	x86_call_membase (s->code, reg1, tree->right->size);
+	x86_mov_reg_membase (s->code, reg1, reg1, tree->left->data.i, 4);
+	x86_call_membase (s->code, reg1, tree->left->size);
 
 	if (tree->size)
 		x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->size);
 }
 
-stmt: CALL_I4 (argl, VFUNC_ADDR (reg)) {
-	int reg1 = tree->right->left->reg1;
+stmt: CALL_I4 (VFUNC_ADDR (reg)) {
+	int reg1 = tree->left->left->reg1;
 
 	x86_mov_reg_membase (s->code, reg1, reg1, 0, 4);
-	x86_call_membase (s->code, reg1, G_STRUCT_OFFSET (MonoClass, vtable + tree->right->data.i));
+	x86_call_membase (s->code, reg1, G_STRUCT_OFFSET (MonoClass, vtable + tree->left->data.i));
 
 	if (tree->size)
 		x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->size);
 }
 
-stmt: CALL_I4 (argl, ADDR_G) {
-	x86_call_mem (s->code, tree->right->data.p);
+stmt: CALL_I4 (ADDR_G) {
+	x86_call_mem (s->code, tree->left->data.p);
 
 	if (tree->size)
 		x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->size);
@@ -1090,15 +1133,15 @@
 		x86_pop_reg (s->code, X86_ECX);
 }
 
-lreg: CALL_I8 (argl, addr) {
+lreg: CALL_I8 (addr) {
 
-	switch (tree->right->data.ainfo.amode) {
+	switch (tree->left->data.ainfo.amode) {
 	case AMImmediate:
-		x86_call_mem (s->code, tree->right->data.ainfo.offset);
+		x86_call_mem (s->code, tree->left->data.ainfo.offset);
 		break;
 	case AMBase:
-		x86_call_membase (s->code, tree->right->data.ainfo.basereg, 
-				  tree->right->data.ainfo.offset);
+		x86_call_membase (s->code, tree->left->data.ainfo.basereg, 
+				  tree->left->data.ainfo.offset);
 		break;
 	default:
 		g_assert_not_reached ();
@@ -1133,9 +1176,9 @@
 }
 
 
-argl: ARG (argl, lreg) {
-	x86_push_reg (s->code, tree->right->reg2);
-	x86_push_reg (s->code, tree->right->reg1);
+stmt: ARG (lreg) {
+	x86_push_reg (s->code, tree->left->reg2);
+	x86_push_reg (s->code, tree->left->reg1);
 }
 
 stmt: BEQ (lreg, lreg) {
@@ -1392,7 +1435,7 @@
 	x86_fst_membase (s->code, X86_EBP, tree->left->data.i, TRUE, TRUE);
 }
 
-argl: ARG (argl, freg) {
+stmt: ARG (freg) {
 	x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 8);
 	x86_fst_membase (s->code, X86_ESP, 0, TRUE, TRUE);
 }
@@ -1467,15 +1510,15 @@
 	x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, TRUE);
 }
 
-freg: CALL_R8 (argl, addr) {
+freg: CALL_R8 (addr) {
 
-	switch (tree->right->data.ainfo.amode) {
+	switch (tree->left->data.ainfo.amode) {
 	case AMImmediate:
-		x86_call_mem (s->code, tree->right->data.ainfo.offset);
+		x86_call_mem (s->code, tree->left->data.ainfo.offset);
 		break;
 	case A_Base:
-		x86_call_membase (s->code, tree->right->data.ainfo.basereg, 
-				  tree->right->data.ainfo.offset);
+		x86_call_membase (s->code, tree->left->data.ainfo.basereg, 
+				  tree->left->data.ainfo.offset);
 		break;
 	default:
 		g_assert_not_reached ();