[Mono-list] patch: support for value types and strings

Dietmar Maurer dietmar@ximian.com
15 Nov 2001 16:15:16 +0100


Got more test programs working: struct.exe, string.exe and
stringbuilder.exe.

Value types: I have introduced a new nonterminal in the BURG grammar,
called vtype. I hope we can eliminate most unnecessary copying that way.

- Dietmar


Index: mono/jit/ChangeLog
===================================================================
RCS file: /cvs/public/mono/mono/jit/ChangeLog,v
retrieving revision 1.42
diff -u -r1.42 ChangeLog
--- mono/jit/ChangeLog	2001/11/10 04:29:12	1.42
+++ mono/jit/ChangeLog	2001/11/15 11:07:52
@@ -1,3 +1,14 @@
+2001-11-15  Dietmar Maurer  <dietmar@ximian.com>
+
+	* Makefile.am (mono_SOURCES): renamed testjit to mono
+
+	* x86.brg: added debugging support 
+
+	* testjit.c: added support for value types, CFG improvements
+
+	* emit-x86.c (enter_method): handle value types
+	(tree_allocate_regs): impl. a better way to handle chain rules
+
 2001-11-10  Dietmar Maurer  <dietmar@ximian.com>
 
 	* x86.brg (INITOBJ): bug fix: initialize data before use,
Index: mono/jit/Makefile.am
===================================================================
RCS file: /cvs/public/mono/mono/jit/Makefile.am,v
retrieving revision 1.9
diff -u -r1.9 Makefile.am
--- mono/jit/Makefile.am	2001/11/09 16:39:49	1.9
+++ mono/jit/Makefile.am	2001/11/15 11:07:52
@@ -3,9 +3,9 @@
 	$(GMODULE_CFLAGS)		\
 	$(GLIB_CFLAGS)			
 
-bin_PROGRAMS = testjit
+bin_PROGRAMS = mono
 
-testjit_SOURCES =		\
+mono_SOURCES =			\
 	codegen.h		\
 	codegen-x86.c		\
 	emit-x86.c		\
@@ -14,9 +14,9 @@
 	regset.c		\
 	mempool.h		\
 	mempool.c		\
-	testjit.c
+	jit.c
 
-testjit_LDADD =				\
+mono_LDADD =				\
 	../metadata/libmetadata.a	\
 	$(GLIB_LIBS)			\
 	$(GMODULE_LIBS) 		\
Index: mono/jit/emit-x86.c
===================================================================
RCS file: /cvs/public/mono/mono/jit/emit-x86.c,v
retrieving revision 1.16
diff -u -r1.16 emit-x86.c
--- mono/jit/emit-x86.c	2001/11/09 06:28:40	1.16
+++ mono/jit/emit-x86.c	2001/11/15 11:07:52
@@ -25,7 +25,7 @@
 static void
 enter_method (MonoMethod *method, gpointer ebp)
 {
-	int i;
+	int i, j;
 	MonoClass *class;
 	MonoObject *o;
 
@@ -33,17 +33,31 @@
 		method->klass->name, method->name);
 
 	ebp += 8;
-	
+
+	if (method->signature->ret->type == MONO_TYPE_VALUETYPE) {
+		int size, align;
+
+		if ((size = mono_type_size (method->signature->ret, &align)) > 4 ||
size == 3) {
+			printf ("VALUERET:%p, ", *((gpointer *)ebp));
+			ebp += sizeof (gpointer);
+		}
+	}
+
 	if (method->signature->hasthis) {
-		o = *((MonoObject **)ebp);
-		class = o->klass;
-		printf ("this:%p[%s.%s], ", o, class->name_space, class->name);
+		if (method->klass->valuetype) {
+			printf ("value:%p, ", *((gpointer *)ebp));
+		} else {
+			o = *((MonoObject **)ebp);
+			class = o->klass;
+			printf ("this:%p[%s.%s], ", o, class->name_space, class->name);
+		}
 		ebp += sizeof (gpointer);
 	}
 
 	for (i = 0; i < method->signature->param_count; ++i) {
 		MonoType *type = method->signature->params [i];
 		int size, align;
+		size = mono_type_size (type, &align);
 
 		switch (type->type) {
 		case MONO_TYPE_BOOLEAN:
@@ -73,17 +87,18 @@
 		case MONO_TYPE_R8:
 			printf ("%f, ", *((double *)(ebp)));
 			break;
-
+		case MONO_TYPE_VALUETYPE: 
+			printf ("[");
+			for (j = 0; j < size; j++)
+				printf ("%02x,", *((guint8*)ebp +j));
+			printf ("], ");
+			break;
 		default:
 			printf ("XX, ");
 		}
-
-		size = mono_type_size (type, &align);
-		if (size < 4) 
-			size = 4;
 
-		ebp += size;
-
+		ebp += size + 3;
+		ebp = (gpointer)((unsigned)ebp & ~(3));
 	}
 
 	printf (")\n");
@@ -433,15 +448,18 @@
 
 	//printf ("RALLOC START %d %p %d\n",  tree->op, rs->free_mask, goal);
 
+	if (nts [0] && kids [0] == tree) {
+		/* chain rule */
+		tree_allocate_regs (kids [0], nts [0], rs);
+		return;
+	}
+
 	for (i = 0; nts [i]; i++)
-		if (kids [i] != tree) /* don't allocate regs for chain rules */
-			tree_allocate_regs (kids [i], nts [i], rs);
+		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 */
-			mono_regset_free_reg (rs, kids [i]->reg1);
-			mono_regset_free_reg (rs, kids [i]->reg2);
-		}
+		mono_regset_free_reg (rs, kids [i]->reg1);
+		mono_regset_free_reg (rs, kids [i]->reg2);
 	}
 
 	switch (goal) {
@@ -631,8 +649,8 @@
 	mono_regset_reserve_reg (cfg->rs, X86_ESP);
 	mono_regset_reserve_reg (cfg->rs, X86_EBP);
 
-	// fixme: remove limitation to 1024 bytes
-	method->addr = cfg->start = cfg->code = g_malloc (1024);
+	// fixme: remove limitation to 4096 bytes
+	method->addr = cfg->start = cfg->code = g_malloc (4096);
 
 	if (mono_jit_dump_forest) {
 		int i;
Index: mono/jit/jit.c
===================================================================
RCS file: /cvs/public/mono/mono/jit/jit.c,v
retrieving revision 1.43
diff -u -r1.43 jit.c
--- mono/jit/jit.c	2001/11/09 22:20:33	1.43
+++ mono/jit/jit.c	2001/11/15 11:07:52
@@ -45,7 +45,7 @@
 };
 #undef OPDEF
 
-#define SET_VARINFO(vi,t,k,o)  do { vi.type=t; vi.kind=k; vi.offset=o;
} while (0)
+#define SET_VARINFO(vi,t,k,o,s)  do { vi.type=t; vi.kind=k;
vi.offset=o; vi.size=s; } while (0)
 
 #define
MAKE_CJUMP(name)                                                      \
 case
CEE_##name:                                                             
\
@@ -62,7 +62,8 @@
 	g_assert (target >= 0 && target <= header->code_size);               
\
 	g_assert (bcinfo [target].is_block_start);                           
\
 	tbb = &cfg->bblocks [bcinfo [target].block_id];                      
\
-	MARK_REACHED (tbb);                                                  
\
+	create_outstack (cfg, bb, stack, sp - stack);                        
\
+	mark_reached (cfg, tbb, bb->outstack, bb->outdepth);                 
\
 	t1->data.p = tbb;                                                    
\
 	ADD_TREE (t1);                                                       
\
 	ip += near_jump ? 1: 4;		                                      \
@@ -354,7 +355,8 @@
 		*svt = VAL_DOUBLE;
 		return MB_TERM_LDIND_R8;
 	case MONO_TYPE_VALUETYPE: {
-		int size =  type->data.klass->instance_size - sizeof (MonoObject);
+		int size, align;
+		size = mono_type_size (type, &align);
 
 		switch (size) {
 		case 4:
@@ -367,8 +369,7 @@
 			*svt = VAL_I32;
 			return MB_TERM_LDIND_U1;
 		default:
-			*svt = VAL_UNKNOWN;
-			return MB_TERM_LDIND_OBJ;
+			g_assert_not_reached ();
 		}
 	}
 	default:
@@ -401,12 +402,14 @@
 	case MONO_TYPE_I:
 	case MONO_TYPE_I4:
 	case MONO_TYPE_U4:
+	case MONO_TYPE_VALUETYPE:
 		*svt = VAL_I32;
 		return MB_TERM_CALL_I4;
 	case MONO_TYPE_CLASS:
 	case MONO_TYPE_OBJECT:
 	case MONO_TYPE_STRING:
 	case MONO_TYPE_PTR:
+	case MONO_TYPE_SZARRAY: 
 		*svt = VAL_POINTER;
 		return MB_TERM_CALL_I4;
 	case MONO_TYPE_I8:
@@ -444,6 +447,9 @@
 	else 
 		printf (" %s", mono_burg_term_string [tree->op]);
 
+	if (tree->op == MB_TERM_ADDR_L)
+		printf ("[%d]", tree->data.i);
+
 	g_assert (!(tree->right && !tree->left));
 
 	mono_print_ctree (tree->left);
@@ -507,12 +513,12 @@
 		cfg->locals_size &= ~(align - 1);
 		cfg->locals_size += size;
 
-		SET_VARINFO (vi, type, kind, - cfg->locals_size);
+		SET_VARINFO (vi, type, kind, - cfg->locals_size, size);
 		g_array_append_val (cfg->varinfo, vi);
 		break;
 	}
 	case MONO_ARGVAR: {
-		SET_VARINFO (vi, type, kind, cfg->args_size + 8);
+		SET_VARINFO (vi, type, kind, cfg->args_size + 8, size);
 		g_array_append_val (cfg->varinfo, vi);
 
 		cfg->args_size += align - 1;
@@ -552,36 +558,47 @@
 mono_allocate_intvar (MonoFlowGraph *cfg, int slot, MonoValueType type)
 {
 	int size, align, vnum;
-
+	
 	g_assert (type != VAL_UNKNOWN);
 
-	if ((vnum = cfg->intvars[slot][type - 1]))
+	if ((vnum = cfg->intvars [type - 1 + slot * VAL_DOUBLE]))
 		return vnum;
 
 	mono_get_val_sizes (type, &size, &align);
 
-	return cfg->intvars[slot][type - 1] = arch_allocate_var (cfg, size,
align, MONO_TEMPVAR, type);
+	return cfg->intvars[type - 1 + slot * VAL_DOUBLE] = arch_allocate_var
(cfg, size, align, MONO_TEMPVAR, type);
 }
 
 /**
  * ctree_create_load:
- * @mp: pointer to a memory pool
- * @addr_type: address type (MB_TERM_ADDR_L or MB_TERM_ADDR_G)
- * @type: the type of the value
+ * @cfg: pointer to the control flow graph
+ * @type: the type of the value to load
  * @addr: the address of the value
  *
  * Creates a tree to load the value at address @addr.
  */
 inline static MBTree *
-ctree_create_load (MonoMemPool *_p, int addr_type, MonoType *type,
gpointer addr, MonoValueType *svt)
+ctree_create_load (MonoFlowGraph *cfg, MonoType *type, MBTree *addr,
MonoValueType *svt)
 {
-	int ldind = map_ldind_type (type, svt);
+	MonoMemPool *mp = cfg->mp;
+	int ldind, size, align, vnum;
 	MBTree *t;
 
-	t = mono_ctree_new_leaf (mp, addr_type);
-	t->data.p = addr;
-	t = mono_ctree_new (mp, ldind, t, NULL);
+	if (type->type == MONO_TYPE_VALUETYPE) {
+		size = mono_type_size (type, &align);
 
+		if (size > 4 || size == 3) {
+		
+			vnum = arch_allocate_var (cfg, size, align, MONO_TEMPVAR,
VAL_UNKNOWN);
+			t = mono_ctree_new (mp, MB_TERM_LDIND_OBJ, addr, NULL);
+			t->data.i = vnum;
+			return t;
+		}
+	}
+
+	ldind = map_ldind_type (type, svt);
+	t = mono_ctree_new (mp, ldind, addr, NULL);
+
 	return t;
 }
 
@@ -713,16 +730,27 @@
 	case MB_TERM_LDIND_R4:
 	case MB_TERM_STIND_R8:
 	case MB_TERM_LDIND_R8: {
-		if (dup)
-			*dup = ctree_create_dup (mp, s);
-		return NULL;
+		if (slot >= 0) {
+			vnum = mono_allocate_intvar (cfg, slot, s->svt);
+
+			if (s->left->op == MB_TERM_ADDR_L && s->left->data.i == vnum) {
+				if (dup)
+					*dup = ctree_create_dup (mp, s);
+				return NULL;
+			}
+			// fall through
+		} else {
+			if (dup)
+				*dup = ctree_create_dup (mp, s);
+			return NULL;
+		}
 	}			
 	default: {
 			g_assert (s->svt != VAL_UNKNOWN);
 
-			if (slot >= 0) 
+			if (slot >= 0) {
 				vnum = mono_allocate_intvar (cfg, slot, s->svt);
-			else {
+			} else {
 				int size, align;
 				mono_get_val_sizes (s->svt, &size, &align);
 				vnum = arch_allocate_var (cfg, size, align, MONO_TEMPVAR, s->svt);
@@ -755,7 +783,7 @@
 
 	cfg->varinfo = g_array_new (FALSE, TRUE, sizeof (MonoVarInfo));
 	
-	SET_VARINFO (vi, 0, 0, 0);
+	SET_VARINFO (vi, 0, 0, 0, 0);
 	g_array_append_val (cfg->varinfo, vi); /* add invalid value at
position 0 */
 
 	cfg->intvars = mono_mempool_alloc0 (mp, sizeof (guint16) * VAL_DOUBLE
* 
@@ -775,7 +803,7 @@
 	g_array_free (cfg->varinfo, TRUE);
 }
 
-#define CREATE_BLOCK(t) {if (!bcinfo [t].is_block_start)
{block_count++;bcinfo [t].is_block_start = 1;}}
+#define CREATE_BLOCK(t) {if (!bcinfo [t].is_block_start)
{block_count++;bcinfo [t].is_block_start = 1; }}
 
 void
 mono_analyze_flow (MonoFlowGraph *cfg)
@@ -898,6 +926,26 @@
 		case CEE_LDELEM_R4:
 		case CEE_LDELEM_R8:
 		case CEE_LDELEM_REF:
+		case CEE_CONV_OVF_I_UN:
+		case CEE_CONV_OVF_U_UN:
+		case CEE_CONV_OVF_I1_UN:
+		case CEE_CONV_OVF_U1_UN:
+		case CEE_CONV_OVF_I2_UN:
+		case CEE_CONV_OVF_U2_UN:
+		case CEE_CONV_OVF_I4_UN:
+		case CEE_CONV_OVF_U4_UN:
+		case CEE_CONV_OVF_I8_UN:
+		case CEE_CONV_OVF_U8_UN:
+		case CEE_CONV_OVF_I:
+		case CEE_CONV_OVF_U:
+		case CEE_CONV_OVF_I1:
+		case CEE_CONV_OVF_U1:
+		case CEE_CONV_OVF_I2:
+		case CEE_CONV_OVF_U2:
+		case CEE_CONV_OVF_I4:
+		case CEE_CONV_OVF_U4:
+		case CEE_CONV_OVF_I8:
+		case CEE_CONV_OVF_U8:
 		case CEE_CONV_I1:
 		case CEE_CONV_U1:
 		case CEE_CONV_I2:
@@ -927,6 +975,7 @@
 		case CEE_STSFLD: 
 		case CEE_STFLD:
 		case CEE_NEWOBJ:
+		case CEE_CPOBJ:
 		case CEE_NEWARR:
 		case CEE_LDTOKEN:
 		case CEE_CALL:
@@ -968,6 +1017,8 @@
 		case CEE_LDLOCA_S:
 		case CEE_STLOC_S:
 		case CEE_LDARG_S: 
+		case CEE_LDARGA_S: 
+		case CEE_STARG_S:
 			ip += 2;
 			break;
 		case CEE_BR_S:
@@ -1003,7 +1054,7 @@
 			for (i = 0; i < n; i++) {
 				target = read32 (ip) + st;
 				ip += 4;
-				CREATE_BLOCK (st + target);			
+				CREATE_BLOCK (target);			
 			}
 			break;
 		}
@@ -1012,6 +1063,7 @@
 			switch (*ip) {
 				
 			case CEE_CEQ:
+			case CEE_CLT:
 				ip++;
 				break;
 			case CEE_LDARG:
@@ -1057,39 +1109,6 @@
 	cfg->block_count = block_count;
 }
 
-static MBTree **
-mono_copy_stack (MBTree **sp, int depth, MonoMemPool *mp)
-{
-	int i;
-	MBTree **copy;
-
-	copy = mono_mempool_alloc (mp, depth * sizeof (MBTree *));
-	
-	sp -= depth;
-
-	for (i = 0; i < depth; i++) {
-		switch (sp [i]->op) {
-		case MB_TERM_LDIND_I1:
-		case MB_TERM_LDIND_U1:
-		case MB_TERM_LDIND_I2:
-		case MB_TERM_LDIND_U2:
-		case MB_TERM_LDIND_I4:
-		case MB_TERM_LDIND_U4:
-		case MB_TERM_LDIND_I8:
-		case MB_TERM_LDIND_R4:
-		case MB_TERM_LDIND_R8:
-			break;
-		default:
-			g_warning ("cant handle type %s (%d)\n", mono_burg_term_string [sp
[i]->op], i);
-				// fixme: store the value somewhere
-			g_assert_not_reached ();
-		}
-	}
-
-	g_assert_not_reached ();
-	return NULL;
-}
-
 /**
  * ves_array_element_address:
  * @this: a pointer to the array object
@@ -1161,10 +1180,69 @@
 #define LOCAL_POS(n)    (1 + n)
 #define LOCAL_TYPE(n)   ((header)->locals [(n)])
 
-#define ARG_POS(n)      (1 + header->num_locals + n)
+#define ARG_POS(n)      (firstarg + n)
 #define ARG_TYPE(n)     ((n) ? (signature)->params [(n) -
(signature)->hasthis] : \
 			(signature)->hasthis ? &method->klass->this_arg: (signature)->params
[(0)])
 
+static void
+create_outstack (MonoFlowGraph *cfg, MonoBBlock *bb, MBTree **stack,
int depth)
+{
+	MonoMemPool *mp = cfg->mp;
+	MBTree **c = stack, *t1, *t2;
+	GPtrArray *forest = bb->forest;
+	int i;
+
+	g_assert (bb->reached);
+
+	if (depth <= 0)
+		return;
+
+	if (bb->outstack) {
+		g_assert (bb->outdepth == depth);
+		return;
+	}
+
+	bb->outdepth = depth;
+	bb->outstack = mono_mempool_alloc (mp, depth * sizeof (MBTree *));
+	
+	for (i = 0; i < depth; i++) {
+		if ((t1 = mono_store_tree (cfg, i, c [i], &t2)))
+			ADD_TREE (t1);
+		bb->outstack [i] = t2;
+	}
+}
+
+static void
+mark_reached (MonoFlowGraph *cfg, MonoBBlock *target, MBTree **stack,
int depth)
+{
+	MonoMemPool *mp = cfg->mp;
+	int i;
+
+	if (target->reached)
+		return;
+
+	target->reached = 1;
+
+	if (depth == 0)
+		return;
+
+	g_assert (stack);
+
+	if (target->instack) {
+		g_assert (target->indepth == depth);
+		return;
+	}
+
+	target->indepth = depth;
+	target->instack = mono_mempool_alloc (mp, depth * sizeof (MBTree *));
+	
+	for (i = 0; i < depth; i++) {
+		target->instack [i] = ctree_create_dup (mp, stack [i]);
+	}
+	
+	
+}
+
 #define MARK_REACHED(bb) do { if (!bb->reached) { bb->reached = 1; }}
while (0)
 
 /**
@@ -1193,6 +1271,7 @@
 	register const unsigned char *ip, *end;
 	GPtrArray *forest;
 	int i, j, depth, repeat_count;
+	int varnum = 0, firstarg = 0, retvtarg = 0;
 	gboolean repeat, superblock_end;
 	MonoBBlock *bb, *tbb;
 
@@ -1207,10 +1286,23 @@
 
 		for (i = 0; i < header->num_locals; ++i) {
 			size = mono_type_size (header->locals [i], &align);
-			arch_allocate_var (cfg, size, align, MONO_LOCALVAR, VAL_UNKNOWN);
+			varnum = arch_allocate_var (cfg, size, align, MONO_LOCALVAR,
VAL_UNKNOWN);
 		}
 	}
+
+	if (signature->ret->type == MONO_TYPE_VALUETYPE) {
+		int size, align;
+
+		size = mono_type_size (signature->ret, &align);
+		
+		retvtarg = varnum = arch_allocate_var (cfg, size, align,
MONO_LOCALVAR, VAL_UNKNOWN);
+		
+		//printf ("VALUETYPE METHOD %s.%s::%s %d\n",
method->klass->name_space, 
+		//method->klass->name, method->name, size);
+	}
 	
+	firstarg = varnum + 1;
+ 
 	if (signature->params_size) {
 		int align, size;
 		int has_this = signature->hasthis;
@@ -1244,19 +1336,11 @@
 			//printf ("BBS %d %d %d %d\n", i, bb->reached, bb->finished,
superblock_end);
 			
 			if (!bb->reached && !superblock_end) {
+				MonoBBlock *sbb = &cfg->bblocks [i - 1];
 
-				if ((depth = sp - stack)) {
+				g_assert (sbb->outdepth == (sp - stack));
 
-					g_assert_not_reached ();
-					//bb->instack = mono_copy_stack;
-					bb->indepth = depth;
-
-					for (j = 0; j < depth; j++) {
-						bb->instack [j] = ctree_create_dup (mp, sp [j]);
-					}
-				}
-
-				MARK_REACHED (bb);
+				mark_reached (cfg, bb, sbb->outstack, sbb->outdepth);
 			} 
 			
 			if (bb->reached) {
@@ -1357,7 +1441,6 @@
 		case CEE_LDOBJ: {
 			guint32 token;
 			MonoClass *c;
-			int size;
 
 			++ip;
 			token = read32 (ip);
@@ -1367,25 +1450,7 @@
 			c = mono_class_get (image, token);
 			g_assert (c->valuetype);
 
-			size = c->instance_size - sizeof (MonoObject);
-			switch (size) {
-			case 4:
-				t1 = mono_ctree_new (mp, MB_TERM_LDIND_U4, *sp, NULL);
-				svt = VAL_I32;
-				break;
-			case 2:
-				t1 = mono_ctree_new (mp, MB_TERM_LDIND_U2, *sp, NULL);
-				svt = VAL_I32;
-				break;
-			case 1:
-				t1 = mono_ctree_new (mp, MB_TERM_LDIND_U1, *sp, NULL);
-				_vt = VAL_I32;
-				break;
-			default:
-				t1 = mono_ctree_new (mp, MB_TERM_LDIND_OBJ, *sp, NULL);
-				svt = VAL_UNKNOWN;
-				break;
-			}
+			t1 = ctree_create_load (cfg, &c->byval_arg, *sp, &svt);
 			PUSH_TREE (t1, svt);
 			break;
 		}
@@ -1433,7 +1498,9 @@
 				t1->data.p = addr;
 				svt = VAL_POINTER;
 			} else {
-				t1 = ctree_create_load (mp, MB_TERM_ADDR_G, field->type, addr,
&svt);
+				t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
+				t1->data.p = addr;
+				t1 = ctree_create_load (cfg, field->type, t1, &svt);
 			}
 
 			PUSH_TREE (t1, svt);
@@ -1531,7 +1598,7 @@
 			else 
 				t1->data.i = field->offset;
 
-			printf ("VALUETYPE %d %d %d\n", klass->valuetype, field->offset,
t1->data.i);
+			//printf ("VALUETYPE %d %d %d\n", klass->valuetype, field->offset,
t1->data.i);
 
 			t1 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t1);
 			t1 = mono_ctree_new (mp, map_stind_type (field->type), t1, sp [1]);
@@ -1566,6 +1633,8 @@
 			// hack: we store n at position 0
 			jt [0] = (MonoBBlock *)n;
 
+			create_outstack (cfg, bb, stack, sp - stack);
+
 			for (i = 1; i <= (n + 1); i++) {
 				if (i > n)
 					target = st;
@@ -1576,7 +1645,7 @@
 				g_assert (target >= 0 && target <= header->code_size);
 				g_assert (bcinfo [target].is_block_start);
 				tbb = &cfg->bblocks [bcinfo [target].block_id];
-				MARK_REACHED (tbb);
+				mark_reached (cfg, tbb, stack, sp - stack);
 				jt [i] = tbb; 
 			}
 
@@ -1613,6 +1682,21 @@
 
 			break;
 		}
+		case CEE_CPOBJ: {
+			MonoClass *class;
+			guint32 token;
+
+			++ip;
+			token = read32 (ip);
+			class = mono_class_get (image, token);
+			ip += 4;
+			sp -= 2;
+
+			t1 = mono_ctree_new (mp, MB_TERM_CPOBJ, sp [0], sp [1]);
+			ADD_TREE (t1);
+			
+			break;
+		}
 		case CEE_NEWOBJ: {
 			MonoMethodSignature *csig;
 			MonoMethod *cm;
@@ -1663,7 +1747,7 @@
 			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);
@@ -1688,7 +1772,7 @@
 			t1->svt = svt;
 
 			if (newarr) {
-				
+     
 				t1 = mono_store_tree (cfg, -1, t1, &t2);
 				g_assert (t1);
 				ADD_TREE (t1);
@@ -1712,7 +1796,7 @@
 			int virtual = *ip == CEE_CALLVIRT;
 			gboolean array_set = FALSE;
 			gboolean array_get = FALSE;
-			int nargs;
+			int nargs, vtype_num = 0;
 
 			++ip;
 			token = read32 (ip);
@@ -1729,6 +1813,9 @@
 			g_assert (csig->call_convention == MONO_CALL_DEFAULT);
 			g_assert (!virtual || csig->hasthis);
 
+			/* fixme: we need to unbox the this pointer for value types */
+			g_assert (!virtual || !cm->klass->valuetype);
+
 			nargs = csig->param_count;
 			arg_sp = sp -= nargs;
 			
@@ -1755,6 +1842,27 @@
 				args_size += sizeof (gpointer);
 			}
 
+			if (csig->ret->type == MONO_TYPE_VALUETYPE) {
+				int size, align;
+
+				if ((size = mono_type_size (csig->ret, &align)) > 4 || size == 3) {
+
+					//printf ("VALUETYPE RETURN %s.%s::%s %d\n",
cm->klass->name_space, 
+					//cm->klass->name, cm->name, size);
+				
+					vtype_num = arch_allocate_var (cfg, size, align, MONO_TEMPVAR,
VAL_UNKNOWN);
+				
+					t2 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
+					t2->data.i = vtype_num;
+				
+					t1 = mono_ctree_new (mp, MB_TERM_ARG, t2, NULL);	
+					ADD_TREE (t1);
+					t1->svt = VAL_POINTER;
+
+					args_size += sizeof (gpointer);
+				}
+			}
+
 			if (array_get) {
 				int size, align, vnum;
 				
@@ -1822,11 +1930,17 @@
 
 				if (csig->ret->type != MONO_TYPE_VOID) {
 
-					t1 = mono_store_tree (cfg, -1, t1, &t2);
-					g_assert (t1);
-					ADD_TREE (t1);
-					PUSH_TREE (t2, t2->svt);
-					
+					if (vtype_num) {
+						ADD_TREE (t1);
+						t1 = mono_ctree_new_leaf (mp, MB_TERM_VTYPE);
+						t1->data.i = vtype_num;
+						PUSH_TREE (t1, VAL_UNKNOWN); 
+					} else {
+						t1 = mono_store_tree (cfg, -1, t1, &t2);
+						g_assert (t1);
+						ADD_TREE (t1);
+						PUSH_TREE (t2, t2->svt);
+					}
 				} else
 					ADD_TREE (t1);
    
@@ -1920,8 +2034,9 @@
 			int n = (*ip) - CEE_LDLOC_0;
 			++ip;
 
-			t1 = ctree_create_load (mp, MB_TERM_ADDR_L, LOCAL_TYPE (n), 
-						(gpointer)LOCAL_POS (n), &svt);
+			t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
+			t1->data.i = LOCAL_POS (n);
+			t1 = ctree_create_load (cfg, LOCAL_TYPE (n), t1, &svt);
 
 			PUSH_TREE (t1, svt);
 			break;
@@ -1929,8 +2044,9 @@
 		case CEE_LDLOC_S: {
 			++ip;
 			
-			t1 = ctree_create_load (mp, MB_TERM_ADDR_L, LOCAL_TYPE (*ip), 
-						(gpointer)LOCAL_POS (*ip), &svt);
+			t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
+			t1->data.i = LOCAL_POS (*ip);
+			t1 = ctree_create_load (cfg, LOCAL_TYPE (*ip), t1, &svt);
 			++ip;
 
 			PUSH_TREE (t1, svt);
@@ -2047,15 +2163,17 @@
 			++ip;
 			t1 = mono_ctree_new_leaf (mp, MB_TERM_BR);
 			target = cli_addr + 2 + (signed char) *ip;
-
+ 
 			g_assert (target >= 0 && target <= header->code_size);
 			g_assert (bcinfo [target].is_block_start);
 			tbb = &cfg->bblocks [bcinfo [target].block_id];
-			MARK_REACHED (tbb);
-			t1->data.p = tbb;
+			create_outstack (cfg, bb, stack, sp - stack);
+			mark_reached (cfg, tbb, bb->outstack, bb->outdepth);
 
+			t1->data.p = tbb;
 			ADD_TREE (t1);
 			++ip;
+
 			superblock_end = TRUE;
 			break;
 		}
@@ -2069,11 +2187,13 @@
 			g_assert (target >= 0 && target <= header->code_size);
 			g_assert (bcinfo [target].is_block_start);
 			tbb = &cfg->bblocks [bcinfo [target].block_id];
-			MARK_REACHED (tbb);
+			create_outstack (cfg, bb, stack, sp - stack);
+			mark_reached (cfg, tbb, bb->outstack, bb->outdepth);
+		      
 			t1->data.p = tbb;
-
 			ADD_TREE (t1);
 			ip += 4;
+
 			superblock_end = TRUE;
 			break;
 		}
@@ -2106,9 +2226,10 @@
 			g_assert (target >= 0 && target <= header->code_size);
 			g_assert (bcinfo [target].is_block_start);
 			tbb = &cfg->bblocks [bcinfo [target].block_id];
-			MARK_REACHED (tbb);
+			create_outstack (cfg, bb, stack, sp - stack);
+			mark_reached (cfg, tbb, bb->outstack, bb->outdepth);
+  
 			t1->data.p = tbb;
-
 			ip += near_jump ? 1: 4;
 			ADD_TREE (t1);
 			break;
@@ -2130,19 +2251,12 @@
 			g_assert (target >= 0 && target <= header->code_size);
 			g_assert (bcinfo [target].is_block_start);
 			tbb = &cfg->bblocks [bcinfo [target].block_id];
-			MARK_REACHED (tbb);
+			create_outstack (cfg, bb, stack, sp - stack);
+			mark_reached (cfg, tbb, bb->outstack, bb->outdepth);
+		    
 			t1->data.p = tbb;
-
 			ip += near_jump ? 1: 4;
 			ADD_TREE (t1);
-
-			if ((tbb->indepth = sp - stack)) {
-				
-				printf ("DEPTH %d\n", tbb->indepth);
-				g_assert_not_reached ();
-			}
-
-
 			break;
 		}
 		case CEE_RET: {
@@ -2174,20 +2288,42 @@
 			int n = (*ip) - CEE_LDARG_0;
 			++ip;
 
-			t1 = ctree_create_load (mp, MB_TERM_ADDR_L, ARG_TYPE (n), 
-						(gpointer)ARG_POS (n), &svt);
+			t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
+			t1->data.i = ARG_POS (n);
+			t1 = ctree_create_load (cfg, ARG_TYPE (n), t1, &svt);
 			PUSH_TREE (t1, svt);
 			break;
 		}
 		case CEE_LDARG_S: {
 			++ip;
 
-			t1 = ctree_create_load (mp, MB_TERM_ADDR_L, ARG_TYPE (*ip), 
-						(gpointer)ARG_POS (*ip), &svt);
+			t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
+			t1->data.i = ARG_POS (*ip);
+			t1 = ctree_create_load (cfg, ARG_TYPE (*ip), t1, &svt);
 			PUSH_TREE (t1, svt);
 			++ip;
 			break;
 		}
+		case CEE_LDARGA_S: {
+			++ip;
+
+			t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
+			t1->data.i = ARG_POS (*ip);
+			PUSH_TREE (t1, VAL_POINTER);
+			++ip;
+			break;
+		}
+		case CEE_STARG_S: {
+			++ip;
+			--sp;
+
+			t1 = ctree_create_store (mp, MB_TERM_ADDR_L, *sp, LOCAL_TYPE (*ip), 
+						 (gpointer)ARG_POS (*ip));
+			++ip;
+
+			ADD_TREE (t1);			
+			break;
+		}
 		case CEE_DUP: {
 			++ip; 
 			sp--;
@@ -2245,6 +2381,13 @@
 			PUSH_TREE (t1, VAL_I64);		
 			break;
 		}
+		case CEE_CONV_U8: {
+			++ip;
+			sp--;
+			t1 = mono_ctree_new (mp, MB_TERM_CONV_I8, *sp, NULL);
+			PUSH_TREE (t1, VAL_I64);		
+			break;
+		}
 		case CEE_CONV_R8: {
 			++ip;
 			sp--;
@@ -2252,11 +2395,36 @@
 			PUSH_TREE (t1, VAL_DOUBLE);		
 			break;
 		}
+		case CEE_CONV_OVF_U4: {
+			// fixme: raise exceptions ?
+			++ip;
+			sp--;
+			t1 = mono_ctree_new (mp, M__TERM_CONV_I4, *sp, NULL);
+			PUSH_TREE (t1, VAL_I32);		
+			break;
+		}
+		case CEE_CONV_OVF_I4_UN: {
+			// fixme: raise exceptions ?
+			++ip;
+			sp--;
+			t1 = mono_ctree_new (mp, MB_TERM_CONV_I4, *sp, NULL);
+			PUSH_TREE (t1, VAL_I32);		
+			break;
+		}
+		case CEE_CONV_OVF_U4_UN: {
+			// fixme: raise exceptions ?
+			++ip;
+			sp--;
+			t1 = mono_ctree_new (mp, MB_TERM_CONV_I4, *sp, NULL);
+			PUSH_TREE (t1, VAL_I32);		
+			break;
+		}
 		case 0xFE: {
 			++ip;			
 			switch (*ip) {
 				
 			MAKE_BI_ALU (CEQ)
+			MAKE_BI_ALU (CLT)
 
 			case CEE_INITOBJ: {
 				MonoClass *class;
@@ -2280,8 +2448,9 @@
 				n = read32 (ip);
 				ip += 4;
 
-				t1 = ctree_create_load (mp, MB_TERM_ADDR_L, ARG_TYPE (n), 
-							(gpointer)ARG_POS (n), &svt);
+				t1 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_L);
+				t1->data.i = ARG_POS (n);
+				t1 = ctree_create_load (cfg, ARG_TYPE (n), t1, &svt);
 				PUSH_TREE (t1, svt);
 				break;
 			}
@@ -2300,7 +2469,9 @@
 	}		
 
         if ((depth = sp - stack)) {
-		g_assert_not_reached ();
+		create_outstack (cfg, bb, stack, sp - stack);
+		//mono_print_forest (forest);
+		//printf ("DEPTH %d %d\n", depth, sp [0]->op);
 	}
 
 	                        } else 
Index: mono/jit/jit.h
===================================================================
RCS file: /cvs/public/mono/mono/jit/jit.h,v
retrieving revision 1.11
diff -u -r1.11 jit.h
--- mono/jit/jit.h	2001/11/07 06:33:48	1.11
+++ mono/jit/jit.h	2001/11/15 11:07:52
@@ -26,6 +26,7 @@
 	MonoValueType type;
 	MonoValueKind kind;
 	int offset;
+	int size;
 } MonoVarInfo;
 
 typedef struct {
@@ -42,6 +43,8 @@
 	GPtrArray    *forest;
 	MBTree      **instack;
 	gint32        indepth;
+	MBTree      **outstack;
+	gint32        outdepth;
 	gint32        addr;
 } MonoBBlock;
 
@@ -53,7 +56,7 @@
 	GArray           *varinfo;
 	gint32            locals_size;
 	gint32            args_size;
-	guint16         **intvars;
+	guint16          *intvars;
 
 	MonoMemPool      *mp;
 	guint8           *start;
Index: mono/jit/x86.brg
===================================================================
RCS file: /cvs/public/mono/mono/jit/x86.brg,v
retrieving revision 1.35
diff -u -r1.35 x86.brg
--- mono/jit/x86.brg	2001/11/10 04:29:12	1.35
+++ mono/jit/x86.brg	2001/11/15 11:07:52
@@ -91,6 +91,33 @@
 #define MB_USE_OPT2(c) c
 #endif
 
+//#define DEBUG
+
+#ifdef DEBUG
+#define MEMCOPY debug_memcpy
+void *MEMCOPY (void *dest, const void *src, size_t n);
+
+#define PRINT_REG(text,reg) \
+g_assert (reg >= 0); \
+x86_push_reg (s->code, X86_EAX); \
+x86_push_reg (s->code, X86_EDX); \
+x86_push_reg (s->code, X86_ECX); \
+x86_push_reg (s->code, reg); \
+x86_push_imm (s->code, reg); \
+x86_push_imm (s->code, text " %d %p\n"); \
+x86_call_code (s->code, printf); \
+x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 3*4); \
+x86_pop_reg (s->code, X86_ECX); \
+x86_pop_reg (s->code, X86_EDX); \
+x86_pop_reg (s->code, X86_EAX); 
+#else
+
+#define MEMCOPY memcpy
+
+#define PRINT_REG(x,y)
+
+#endif
+
 /* The call instruction for virtual functions must have a known
  * size (used by x86_magic_trampoline)
  */
@@ -116,9 +143,9 @@
 %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 NEWARR NEWOBJ POP INITOBJ
+%term CEQ CLT
+%term CONV_I4 CONV_I1 CONV_I2 CONV_I8 CONV_U8 CONV_R8
+%term INTF_ADDR VFUNC_ADDR NOP NEWARR NEWOBJ CPOBJ POP INITOBJ VTYPE
 %term LDLEN
 
 #
@@ -220,6 +247,8 @@
 }
 
 stmt: STIND_I4 (addr, reg) {
+	PRINT_REG ("STIND_I4", tree->right->reg1);
+
 	switch (tree->left->data.ainfo.amode) {
 
 	case AMImmediate:
@@ -244,6 +273,8 @@
 }
 
 stmt: STIND_I1 (addr, reg) {
+	PRINT_REG ("STIND_I1", tree->right->reg1);
+
 	switch (tree->left->data.ainfo.amode) {
 
 	case AMImmediate:
@@ -267,7 +298,84 @@
 	}
 }
 
+stmt: STIND_I2 (addr, reg) {
+	PRINT_REG ("STIND_I2", tree->right->reg1);
+
+	switch (tree->left->data.ainfo.amode) {
+
+	case AMImmediate:
+		x86_mov_mem_reg (s->code, tree->left->data.ainfo.offset,
tree->right->reg1, 2);
+		break;
+		
+	case AMBase:
+		x86_mov_membase_reg (s->code, tree->left->data.ainfo.basereg, 
+				     tree->left->data.ainfo.offset, tree->right->reg1, 2);
+		break;		
+	case AMIndex:
+		x86_mov_memindex_reg (s->code, X86_NOBASEREG,
tree->left->data.ainfo.offset,
+				      tree->left->data.ainfo.indexreg,
tree->left->data.ainfo.shift,
+				      tree->right->reg1, 2);
+		break;		
+	case AMBaseIndex:
+		x86_mov_memindex_reg (s->code, tree->left->data.ainfo.basereg,
tree->left->data.ainfo.offset,
+				      tree->left->data.ainfo.indexreg,
tree->left->data.ainfo.shift,
+				      tree->right->reg1, 2);
+		break;		
+	}
+}
+
+reg: LDIND_I1 (addr) {
+	switch (tree->left->data.ainfo.amode) {
+
+	case AMImmediate:
+		x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset,
1);
+		break;
+
+	case AMBase:
+		x86_mov_reg_membase (s->code, tree->reg1,
tree->left->data.ainfo.basereg, 
+				     tree->left->data.ainfo.offset, 1);
+		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, 1);
+		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, 1);
+		break;		
+	}
+
+	PRINT_REG ("LDIND_I1", tree->reg1);
+}
+
+reg: LDIND_I2 (addr) {
+	switch (tree->left->data.ainfo.amode) {
+
+	case AMImmediate:
+		x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset,
2);
+		break;
+
+	case AMBase:
+		x86_mov_reg_membase (s->code, tree->reg1,
tree->left->data.ainfo.basereg, 
+				     tree->left->data.ainfo.offset, 2);
+		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, 2);
+		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, 2);
+		break;		
+	}
+
+	PRINT_REG ("LDIND_I2", tree->reg1);
+}
+
 reg: LDIND_I4 (addr) {
+
 	switch (tree->left->data.ainfo.amode) {
 
 	case AMImmediate:
@@ -288,29 +396,58 @@
 				      tree->left->data.ainfo.shift, 4);
 		break;		
 	}
+
+	PRINT_REG ("LDIND_I4", tree->reg1);
 }
 
 reg: LDIND_U1 (addr) {
 	switch (tree->left->data.ainfo.amode) {
 
 	case AMImmediate:
-		x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.ainfo.offset,
1);
+		x86_widen_mem (s->code, tree->reg1, tree->left->data.ainfo.offset,
FALSE, FALSE);
 		break;
 
 	case AMBase:
-		x86_mov_reg_membase (s->code, tree->reg1,
tree->left->data.ainfo.basereg, 
-				     tree->left->data.ainfo.offset, 1);
+		x86_widen_membase (s->code, tree->reg1,
tree->left->data.ainfo.basereg, 
+				   tree->left->data.ainfo.offset, FALSE, FALSE);
 		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, 1);
+		x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG,
tree->left->data.ainfo.offset,
+				    tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
FALSE, FALSE);
 		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, 1);
+		x86_widen_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, FALSE, FALSE);
+		break;		
+	}
+
+	PRINT_REG ("LDIND_U1", tree->reg1);
+}
+
+reg: LDIND_U2 (addr) {
+	switch (tree->left->data.ainfo.amode) {
+
+	case AMImmediate:
+		x86_widen_mem (s->code, tree->reg1, tree->_eft->data.ainfo.offset,
FALSE, TRUE);
+		break;
+
+	case AMBase:
+		x86_widen_membase (s->code, tree->reg1,
tree->left->data.ainfo.basereg, 
+				   tree->left->data.ainfo.offset, FALSE, TRUE);
+		break;		
+	case AMIndex:
+		x86_widen_memindex (s->code, tree->reg1, X86_NOBASEREG,
tree->left->data.ainfo.offset,
+				    tree->left->data.ainfo.indexreg, tree->left->data.ainfo.shift,
FALSE, TRUE);
+		break;		
+	case AMBaseIndex:
+		x86_widen_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, FALSE, TRUE);
 		break;		
 	}
+
+	PRINT_REG ("LDIND_U2", tree->reg1);
 }
 
 reg: LDIND_U4 (addr) {
@@ -334,6 +471,8 @@
 				      tree->left->data.ainfo.shift, 4);
 		break;		
 	}
+
+	PRINT_REG ("LDIND_U4", tree->reg1);
 }
 
 locaddr: ADDR_L 10 {
@@ -341,9 +480,8 @@
 }
 
 reg: ADDR_L 1 {
-	int offset = g_array_index (s->varinfo, MonoVarInfo,
tree->data.i).offset;
-	x86_mov_reg_reg (s->code, tree->reg1, X86_EBP, 4);
-	x86_alu_reg_imm (s->code, X86_ADD, tree->reg1, offset); 
+	int offset = g_array_index (s->varinfo, MonoVarInfo,
tree->data.i).offset;  
+	x86_lea_membase (s->code, tree->reg1, X86_EBP, offset);
 }
 
 reg: CONV_I1 (reg) {
@@ -362,40 +500,12 @@
 	x86_mov_reg_imm (s->code, tree->reg1, tree->data.i);
 }
 
-# do nothing
-reg: CONV_I4 (reg) 
-
-reg: LDIND_I4 (reg) {
-	x86_mov_reg_membase (s->code, tree->reg1, tree->left->reg1, 0, 4);
-}
-
-reg: LDIND_I1 (locaddr) {
-	x86_widen_membase (s->code, tree->reg1, X86_EBP, tree->left->data.i,
TRUE, FALSE);
-}
-
-reg: LDIND_U1 (locaddr) {
-	x86_widen_membase (s->code, tree->reg1, X86_EBP, tree->left->data.i,
FALSE, FALSE);
-}
-
-reg: LDIND_I2 (locaddr) {
-	x86_widen_membase (s->code, tree->reg1, X86_EBP, tree->left->data.i,
TRUE, TRUE);
-}
-
-reg: LDIND_U2 (locaddr) {
-	x86_widen_membase (s->code, tree->reg1, X86_EBP, tree->left->data.i,
FALSE, TRUE);
-}
-
-reg: LDIND_I4 (locaddr) {
-	x86_mov_reg_membase (s->code, tree->reg1, X86_EBP, tree->left->data.i,
4);
-}
-
-reg: LDIND_U4 (locaddr) {
-	x86_mov_reg_membase (s->code, tree->reg1, X86_EBP, tree->left->data.i,
4);
-}
+reg: CONV_I4 (reg) {
+	if (tree->reg1 != tree->left->reg1)
+		x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
+	PRINT_REG ("CONV_I4", tree->left->reg1);
+} 
 
-reg: LDIND_I4 (ADDR_G) {
-	x86_mov_reg_mem (s->code, tree->reg1, tree->left->data.p, 4);
-}
 
 reg: MUL (reg, reg) {
 	if (tree->reg1 != tree->left->reg1)
@@ -474,11 +584,17 @@
 }
 
 reg: CEQ (reg, reg) {
-	x86_test_reg_reg (s->code, tree->left->reg1, tree->right->reg1);
+	x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1,
tree->right->reg1);
 	x86_set_reg (s->code, X86_CC_EQ, tree->reg1, TRUE);
 	x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
 }
 
+reg: CLT (reg, reg) {
+	x86_alu_reg_reg (s->code, X86_CMP, tree->left->reg1,
tree->right->reg1);
+	x86_set_reg (s->code, X86_CC_LT, tree->reg1, TRUE);
+	x86_widen_reg (s->code, tree->reg1, tree->reg1, FALSE, FALSE);
+}
+
 reg: AND (reg, reg) {
 	if (tree->reg1 != tree->left->reg1)
 		x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
@@ -948,11 +1064,6 @@
 	x86_push_imm (s->code, tree->left->data.i);
 }
 
-stmt: ARG (LDIND_OBJ (reg)) {
-      // fixme:
-      g_assert_not_reached ();
-}
-
 reg: CALL_I4 (CONST_I4) {
 	
 	x86_call_code (s->code, tree->left->data.p);
@@ -998,6 +1109,8 @@
 	if (tree->data.i)
 		x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.i);
 
+	PRINT_REG ("CONV_I4(VIRTUAL)", tree->reg1);
+
 	g_assert (tree->reg1 == X86_EAX);
 }
 
@@ -1063,7 +1176,7 @@
 	x86_mov_reg_imm (s->code, tree->reg2, *(gint32 *)(&tree->data.p + 4));
 }
 
-lreg: CONV_I8 (CONST_I4) 1 {
+lreg: CONV_I8 (CONST_I4) {
 	x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
 
 	if (tree->left->data.i >= 0)
@@ -1072,6 +1185,29 @@
 		x86_mov_reg_imm (s->code, tree->reg2, -1);		
 }
 
+lreg: CONV_I8 (reg) {
+	guint8 *i1;
+
+	if (tree->reg1 != tree->left->reg1)
+		x86_mov_reg_reg (s->code, tree->reg1, tree->left->reg1, 4);
+
+	// fixme: check if the branch8 is to the right location
+	x86_breakpoint (s->code);
+
+	x86_alu_reg_imm (s->code, X86_CMP, tree->left->reg1, 0);
+	x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
+	x86_branch8 (s->code, X86_CC_GE, 4, TRUE);
+	i1 = s->code;
+	x86_mov_reg_imm (s->code, tree->reg2, -1); 
+	g_assert ((s->code - i1) == 4);
+	g_assert_not_reached ();
+}
+
+lreg: CONV_U8 (CONST_I4) 1 {
+	x86_mov_reg_imm (s->code, tree->reg1, tree->left->data.i);
+	x86_alu_reg_reg (s->code, X86_XOR, tree->reg2, tree->reg2);
+}
+
 stmt: STIND_I8 (locaddr, lreg) {
 	x86_mov_membase_reg (s->code, X86_EBP, tree->left->data.i,
 			     tree->right->reg1, 4);
@@ -1722,6 +1858,109 @@
 	}
 }
 
+# support for value types
+
+vtype: VTYPE
+
+vtype: LDIND_OBJ (reg) {
+	int treg = X86_EAX;
+	int offset = g_array_index (s->varinfo, MonoVarInfo,
tree->data.i).offset;
+	int size = g_array_index (s->varinfo, MonoVarInfo, tree->data.i).size;
+
+	if (tree->left->reg1 == X86_EAX)
+		treg = X86_ECX;
+
+	x86_push_reg (s->code, X86_EAX);
+	x86_push_reg (s->code, X86_EDX);
+	x86_push_reg (s->code, X86_ECX);
+
+	x86_push_imm (s->code, size);
+	x86_push_reg (s->code, tree->left->reg1);
+	x86_lea_membase (s->code, treg, X86_EBP, offset);
+	x86_push_reg (s->code, treg);
+	x86_call_code (s->code, MEMCOPY);
+	x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
+
+	x86_pop_reg (s->code, X86_ECX);
+	x86_pop_reg (s->code, X86_EDX);
+	x86_pop_reg (s->code, X86_EAX);
+}
+
+stmt: STIND_OBJ (reg, vtype) {
+	int treg = X86_EAX;
+	int offset = g_array_index (s->varinfo, MonoVarInfo,
tree->right->data.i).offset;
+	int size = g_array_index (s->varinfo, MonoVarInfo,
tree->right->data.i).size;
+
+	if (tree->left->reg1 == X86_EAX)
+		treg = X86_ECX;
+
+	x86_push_reg (s->code, X86_EAX);
+	x86_push_reg (s->code, X86_EDX);
+	x86_push_reg (s->code, X86_ECX);
+
+	x86_push_imm (s->code, size);
+	x86_lea_membase (s->code, treg, X86_EBP, offset);
+	x86_push_reg (s->code, treg);
+	x86_push_reg (s->code, tree->left->reg1);
+	x86_call_code (s->code, MEMCOPY);
+	x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
+
+	x86_pop_reg (s->code, X86_ECX);
+	x86_pop_reg (s->code, X86_EDX);
+	x86_pop_reg (s->code, X86_EAX);
+}
+
+stmt: ARG (vtype) {
+	int treg = X86_EAX;
+	int offset = g_array_index (s->varinfo, MonoVarInfo,
tree->left->data.i).offset;
+	int size = g_array_index (s->varinfo, MonoVarInfo,
tree->left->data.i).size;
+	int sa;
+	
+	sa = size + 3;
+	sa &= ~3;
+
+	/* reserve space for the argument */
+	x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, sa);
+
+	x86_push_reg (s->code, X86_EAX);
+	x86_push_reg (s->code, X86_EDX);
+	x86_push_reg (s->code, X86_ECX);
+
+	x86_push_imm (s->code, size);
+
+	x86_lea_membase (s->code, treg, X86_EBP, offset);
+	x86_push_reg (s->code, treg);
+
+	x86_lea_membase (s->code, treg, X86_ESP, 5*4);
+	x86_push_reg (s->code, treg);
+
+	x86_call_code (s->code, MEMCOPY);
+	x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
+
+	x86_pop_reg (s->code, X86_ECX);
+	x86_pop_reg (s->code, X86_EDX);
+	x86_pop_reg (s->code, X86_EAX);
+}
+
+stmt: RETV (vtype) {
+	int treg = X86_EAX;
+	int offset = g_array_index (s->varinfo, MonoVarInfo,
tree->left->data.i).offset;
+	int size = g_array_index (s->varinfo, MonoVarInfo,
tree->left->data.i).size;
+
+	x86_push_imm (s->code, size);
+	x86_lea_membase (s->code, treg, X86_EBP, offset);
+	x86_push_reg (s->code, treg);
+	x86_push_membase (s->code, X86_EBP, 8);
+
+	x86_call_code (s->code, MEMCOPY);
+	x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 12);
+
+	if (!tree->last_instr) {
+		tree->is_jump = 1;
+		x86_jump32 (s->code, s->epilog - 5);      
+	}
+}
+
 %% 
 
 #include "jit.h"
@@ -1776,3 +2015,18 @@
 	return mono_ctree_new (mp, op, NULL, NULL);
 }
 
+#ifdef DEBUG
+void *
+MEMCOPY (void *dest, const void *src, size_t n)
+{
+	int i, l = n;
+
+	printf ("MEMCPY(%p to %p [%d]) ", src, dest, n);
+
+	for (i = 0; i < l; i++)
+		printf ("%02x ", *((guint8 *)src + i));
+	printf ("\n");
+	
+	return memcpy (dest, src, n);
+}
+#endif
Index: mono/metadata/class.c
===================================================================
RCS file: /cvs/public/mon_/mono/metadata/class.c,v
retrieving revision 1.52
diff -u -r1.52 class.c
--- mono/metadata/class.c	2001/11/14 15:18:56	1.52
+++ mono/metadata/class.c	2001/11/15 11:07:53
@@ -946,6 +946,7 @@
 		class = mono_class_create_from_typespec (image, type_token);
 		break;
 	default:
+		g_warning ("unknown token type %x", type_token & 0xff000000);
 		g_assert_not_reached ();
 	}
 	
Index: mono/tests/Makefile.am
===================================================================
RCS file: /cvs/public/mono/mono/tests/Makefile.am,v
retrieving revision 1.21
diff -u -r1.21 Makefile.am
--- mono/tests/Makefile.am	2001/11/14 15:18:56	1.21
+++ mono/tests/Makefile.am	2001/11/15 11:07:53
@@ -1,6 +1,6 @@
 
 TEST_PROG=../interpreter/mint
-JITTEST_PROG=../jit/testjit
+JITTEST_PROG=../jit/mono
 
 CSC=csc