[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