[Mono-list] jit patch: console.exe works
Dietmar Maurer
dietmar@ximian.com
16 Nov 2001 15:57:52 +0100
Index: mono/jit/ChangeLog
===================================================================
RCS file: /cvs/public/mono/mono/jit/ChangeLog,v
retrieving revision 1.43
diff -u -r1.43 ChangeLog
--- mono/jit/ChangeLog 2001/11/15 11:11:20 1.43
+++ mono/jit/ChangeLog 2001/11/16 10:55:38
@@ -1,3 +1,13 @@
+2001-11-16 Dietmar Maurer <dietmar@ximian.com>
+
+ * x86.brg (STRING_ARG): impl. a way to marshal strings. This
+ will be extensible to handle all possible kinds of marshalling
+ requirements.
+
+ * jit.c (map_call_type): added MB_TERM_CALL_VOID
+ (mono_analyze_stack): impl. LDELEMA, reimplemented CALL
+ instructions to handle this arguments more effectively.
+
2001-11-15 Dietmar Maurer <dietmar@ximian.com>
* Makefile.am (mono_SOURCES): renamed testjit to mono
Index: mono/jit/emit-x86.c
===================================================================
RCS file: /cvs/public/mono/mono/jit/emit-x86.c,v
retrieving revision 1.17
diff -u -r1.17 emit-x86.c
--- mono/jit/emit-x86.c 2001/11/15 11:11:20 1.17
+++ mono/jit/emit-x86.c 2001/11/16 10:55:38
@@ -633,10 +633,10 @@
g_assert (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL));
g_assert (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL));
- //g_assert (!method->addr);
- printf ("Start JIT compilation %p %p\n", method, method->addr);
- printf ("Start JIT compilation of %s.%s:%s\n", method->klass->name_space,
- method->klass->name, method->name);
+ if (mono_jit_trace_calls) {
+ printf ("Start JIT compilation of %s.%s:%s\n", method->klass->name_space,
+ method->klass->name, method->name);
+ }
cfg = mono_cfg_new (method, mp);
@@ -681,8 +681,10 @@
mono_mempool_destroy (mp);
- printf ("END JIT compilation of %s.%s:%s %p %p\n", method->klass->name_space,
- method->klass->name, method->name, method, method->addr);
+ if (mono_jit_trace_calls) {
+ printf ("END JIT compilation of %s.%s:%s %p %p\n", method->klass->name_space,
+ method->klass->name, method->name, method, method->addr);
+ }
return method->addr;
}
Index: mono/jit/jit.c
===================================================================
RCS file: /cvs/public/mono/mono/jit/jit.c,v
retrieving revision 1.44
diff -u -r1.44 jit.c
--- mono/jit/jit.c 2001/11/15 11:11:20 1.44
+++ mono/jit/jit.c 2001/11/16 10:55:38
@@ -114,23 +114,10 @@
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->data.i = s; \
- t1 = mono_ctree_new (mp, op, t1, sp [2]); \
- ADD_TREE (t1); \
- break; \
-}
-*/
-
-#define MAKE_STELEM(name, op, s) \
-case CEE_##name: { \
- ++ip; \
- sp -= 3; \
t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4); \
t1->data.i = s; \
t1 = mono_ctree_new (mp, MB_TERM_MUL, sp [1], t1); \
@@ -393,6 +380,8 @@
{
switch (type->type) {
case MONO_TYPE_VOID:
+ *svt = VAL_UNKNOWN;
+ return MB_TERM_CALL_VOID;
case MONO_TYPE_I1:
case MONO_TYPE_U1:
case MONO_TYPE_BOOLEAN:
@@ -402,9 +391,11 @@
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_VALUETYPE:
+ *svt = VAL_I32;
+ return MB_TERM_CALL_VOID;
case MONO_TYPE_CLASS:
case MONO_TYPE_OBJECT:
case MONO_TYPE_STRING:
@@ -447,8 +438,11 @@
else
printf (" %s", mono_burg_term_string [tree->op]);
- if (tree->op == MB_TERM_ADDR_L)
+ switch (tree->op) {
+ case MB_TERM_ADDR_L:
printf ("[%d]", tree->data.i);
+ break;
+ }
g_assert (!(tree->right && !tree->left));
@@ -974,6 +968,7 @@
case CEE_LDFLDA:
case CEE_STSFLD:
case CEE_STFLD:
+ case CEE_LDELEMA:
case CEE_NEWOBJ:
case CEE_CPOBJ:
case CEE_NEWARR:
@@ -1606,6 +1601,35 @@
ADD_TREE (t1);
break;
}
+ case CEE_LDELEMA: {
+ MonoClass *class;
+ guint32 esize, token;
+
+ ++ip;
+ token = read32 (ip);
+ ip += 4;
+ sp -= 2;
+
+ class = mono_class_get (image, token);
+
+ if (!class->inited)
+ mono_jit_init_class (class);
+
+ esize = mono_class_instance_size (class);
+ if (class->valuetype)
+ esize -= sizeof (MonoObject);
+
+ t1 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
+ t1->data.i = esize;
+ t1 = mono_ctree_new (mp, MB_TERM_MUL, sp [1], t1);
+ t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
+ t2->data.i = G_STRUCT_OFFSET (MonoArray, vector);
+ t2 = mono_ctree_new (mp, MB_TERM_ADD, sp [0], t2);
+ t1 = mono_ctree_new (mp, MB_TERM_ADD, t1, t2);
+
+ PUSH_TREE (t1, VAL_POINTER);
+ break;
+ }
case CEE_NOP: {
++ip;
break;
@@ -1699,6 +1723,7 @@
}
case CEE_NEWOBJ: {
MonoMethodSignature *csig;
+ MethodCallInfo *ci;
MonoMethod *cm;
MBTree *this = NULL;
guint32 token;
@@ -1713,6 +1738,9 @@
g_assert (cm);
g_assert (!strcmp (cm->name, ".ctor"));
+ ci = mono_mempool_alloc0 (mp, sizeof (MethodCallInfo));
+ ci->m = cm;
+
csig = cm->signature;
g_assert (csig->call_convention == MONO_CALL_DEFAULT);
g_assert (csig->hasthis);
@@ -1720,13 +1748,10 @@
arg_sp = sp -= csig->param_count;
if (cm->klass->parent == mono_defaults.array_class) {
-
newarr = TRUE;
this = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
this->data.p = cm;
-
- } else {
-
+ } else {
this = mono_ctree_new_leaf (mp, MB_TERM_NEWOBJ);
this->data.p = cm->klass;
this->svt = VAL_POINTER;
@@ -1734,7 +1759,6 @@
t1 = mono_store_tree (cfg, -1, this, &this);
g_assert (t1);
ADD_TREE (t1);
-
}
for (i = csig->param_count - 1; i >= 0; i--) {
@@ -1744,18 +1768,22 @@
args_size += (size + 3) & ~3;
}
- t1 = mono_ctree_new (mp, MB_TERM_ARG, this, NULL);
- ADD_TREE (t1);
- args_size += sizeof (gpointer);
-
+ args_size += sizeof (gpointer); /* this argument */
+ ci->args_size = args_size;
+
if (newarr) {
t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
t2->data.p = mono_array_new_va;
- t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, t2, NULL);
- t1->data.i = args_size;
- t1->svt = VAL_I32;
+ t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, this, t2);
+ t1->data.p = ci;
+ t1->svt = VAL_POINTER;
+
+ t1 = mono_store_tree (cfg, -1, t1, &t2);
+ g_assert (t1);
+ ADD_TREE (t1);
+ PUSH_TREE (t2, t2->svt);
} else {
@@ -1765,30 +1793,22 @@
t2 = mono_ctree_new_leaf (mp, MB_TERM_ADDR_G);
t2->data.p = (char *)cm + G_STRUCT_OFFSET (MonoMethod, addr);
t2 = mono_ctree_new (mp, MB_TERM_LDIND_I4, t2, NULL);
- }
-
- t1 = mono_ctree_new (mp, map_call_type (csig->ret, &svt), t2, NULL);
- t1->data.i = args_size;
- t1->svt = svt;
- if (newarr) {
-
- t1 = mono_store_tree (cfg, -1, t1, &t2);
- g_assert (t1);
- ADD_TREE (t1);
- PUSH_TREE (t2, t2->svt);
-
- } else {
+ t1 = mono_ctree_new (mp, map_call_type (csig->ret, &svt), this, t2);
+ t1->data.p = ci;
+ t1->svt = svt;
ADD_TREE (t1);
t1 = ctree_create_dup (mp, this);
PUSH_TREE (t1, t1->svt);
+
}
break;
}
case CEE_CALL:
case CEE_CALLVIRT: {
MonoMethodSignature *csig;
+ MethodCallInfo *ci;
MonoMethod *cm;
MBTree *this = NULL;
guint32 token;
@@ -1796,6 +1816,7 @@
int virtual_= *ip == CEE_CALLVIRT;
gboolean array_set = FALSE;
gboolean array_get = FALSE;
+ gboolean pinvoke = FALSE;
int nargs, vtype_num = 0;
++ip;
@@ -1804,7 +1825,13 @@
cm = mono_get_method (image, token, NULL);
g_assert (cm);
-
+
+ ci = mono_mempool_alloc0 (mp, sizeof (MethodCallInfo));
+ ci->m = cm;
+
+ if (cm->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
+ pinvoke = TRUE;
+
if ((cm->flags & METHOD_ATTRIBUTE_FINAL) ||
!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
virtual = 0;
@@ -1829,7 +1856,11 @@
}
for (i = nargs - 1; i >= 0; i--) {
- t1 = mono_ctree_new (mp, MB_TERM_ARG, arg_sp [i], NULL);
+ if (pinvoke && cm->signature->params [i]->type == MONO_TYPE_STRING) {
+ t1 = mono_ctree_new (mp, MB_TERM_STRING_ARG, arg_sp [i], NULL);
+ } else {
+ t1 = mono_ctree_new (mp, MB_TERM_ARG, arg_sp [i], NULL);
+ }
ADD_TREE (t1);
size = mono_type_size (cm->signature->params [i], &align);
args_size += (size + 3) & ~3;
@@ -1837,40 +1868,27 @@
if (csig->hasthis) {
this = *(--sp);
- t1 = mono_ctree_new (mp, MB_TERM_ARG, this, NULL);
- ADD_TREE (t1);
args_size += sizeof (gpointer);
- }
+ } else
+ this = mono_ctree_new_leaf (mp, MB_TERM_NOP);
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);
-
+ if ((size = mono_type_size (csig->ret, &align)) > 4 || size == 3)
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);
- }
}
+ ci->args_size = args_size;
+ ci->vtype_num = vtype_num;
+
if (array_get) {
int size, align, vnum;
t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
t2->data.p = ves_array_element_address;
- t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, t2, NULL);
- t1->data.i = args_size;
+ t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, this, t2);
+ t1->data.p = ci;
t1 = mono_ctree_new (mp, map_ldind_type (csig->ret, &svt), t1, NULL);
t1->svt = svt;
@@ -1892,8 +1910,8 @@
t2 = mono_ctree_new_leaf (mp, MB_TERM_CONST_I4);
t2->data.p = ves_array_element_address;
- t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, t2, NULL);
- t1->data.i = args_size;
+ t1 = mono_ctree_new (mp, MB_TERM_CALL_I4, this, t2);
+ t1->data.p = ci;
t1 = mono_ctree_new (mp, map_stind_type (csig->params [nargs]), t1, arg_sp [nargs]);
ADD_TREE (t1);
@@ -1901,16 +1919,13 @@
} else {
if (virtual) {
-
- t2 = ctree_create_dup (mp, this);
-
if (!cm->klass->metadata_inited)
mono_class_metadata_init (cm->klass);
if (cm->klass->flags & TYPE_ATTRIBUTE_INTERFACE)
- t2 = mono_ctree_new (mp, MB_TERM_INTF_ADDR, t2, NULL);
+ t2 = mono_ctree_new_leaf (mp, MB_TERM_INTF_ADDR);
else
- t2 = mono_ctree_new (mp, MB_TERM_VFUNC_ADDR, t2, NULL);
+ t2 = mono_ctree_new_leaf (mp, MB_TERM_VFUNC_ADDR);
t2->data.m = cm;
@@ -1924,8 +1939,8 @@
t2 = mono_ctree_new (mp, MB_TERM_LDIND_I4, t2, NULL);
}
- t1 = mono_ctree_new (mp, map_call_type (csig->ret, &svt), t2, NULL);
- t1->data.i = args_size;
+ t1 = mono_ctree_new (mp, map_call_type (csig->ret, &svt), this, t2);
+ t1->data.p = ci;
t1->svt = svt;
if (csig->ret->type != MONO_TYPE_VOID) {
@@ -2317,7 +2332,7 @@
++ip;
--sp;
- t1 = ctree_create_store (mp, MB_TERM_ADDR_L, *sp, LOCAL_TYPE (*ip),
+ t1 = ctree_create_store (mp, MB_TERM_ADDR_L, *sp, ARG_TYPE (*ip),
(gpointer)ARG_POS (*ip));
++ip;
@@ -2479,7 +2494,7 @@
} else {
superblock_end = TRUE;
- printf ("unreached block %d\n", i);
+ //printf ("unreached block %d\n", i);
repeat = TRUE;
g_assert (repeat_count < 10);
}
Index: mono/jit/jit.h
===================================================================
RCS file: /cvs/public/mono/mono/jit/jit.h,v
retrieving revision 1.12
diff -u -r1.12 jit.h
--- mono/jit/jit.h 2001/11/15 11:11:20 1.12
+++ mono/jit/jit.h 2001/11/16 10:55:38
@@ -65,6 +65,12 @@
guint32 epilog;
} MonoFlowGraph;
+typedef struct {
+ MonoMethod *m;
+ int args_size;
+ int vtype_num;
+} MethodCallInfo;
+
extern gboolean mono_jit_dump_asm;
extern gboolean mono_jit_dump_forest;
extern gboolean mono_jit_trace_calls;
Index: mono/jit/x86.brg
===================================================================
RCS file: /cvs/public/mono/mono/jit/x86.brg,v
retrieving revision 1.36
diff -u -r1.36 x86.brg
--- mono/jit/x86.brg 2001/11/15 11:11:20 1.36
+++ mono/jit/x86.brg 2001/11/16 10:55:38
@@ -66,6 +66,7 @@
gpointer p;
MonoBBlock *bb;
MonoMethod *m;
+ MethodCallInfo *ci;
X86AddressInfo ainfo;
} data;
};
@@ -139,7 +140,7 @@
%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 CALL_I4 CALL_I8 CALL_R8
+%term ADDR_L ADDR_G ARG STRING_ARG CALL_I4 CALL_I8 CALL_R8 CALL_VOID
%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
@@ -1056,6 +1057,24 @@
x86_push_reg (s->code, tree->left->reg1);
}
+# fixme: we must free the allocated strings somewhere
+stmt: STRING_ARG (reg) {
+ x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
+ 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_call_code (s->code, mono_string_to_utf8);
+ x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, 4);
+
+ x86_mov_membase_reg (s->code, X86_ESP, 12, X86_EAX, 4);
+
+ x86_pop_reg (s->code, X86_EDX);
+ x86_pop_reg (s->code, X86_ECX);
+ x86_pop_reg (s->code, X86_EAX);
+}
+
stmt: ARG (ADDR_G) {
x86_push_imm (s->code, tree->left->data.p);
}
@@ -1063,86 +1082,217 @@
stmt: ARG (CONST_I4) "MB_USE_OPT1(0)" {
x86_push_imm (s->code, tree->left->data.i);
}
+
+this: reg
+
+this: NOP
-reg: CALL_I4 (CONST_I4) {
+reg: CALL_I4 (this, reg) {
+ MethodCallInfo *ci = tree->data.ci;
+ int treg = X86_EAX;
+ int lreg = tree->left->reg1;
+ int rreg = tree->right->reg1;
- x86_call_code (s->code, tree->left->data.p);
+ if (lreg == treg || rreg == treg)
+ treg = X86_EDX;
+ if (lreg == treg || rreg == treg)
+ treg = X86_ECX;
+ if (lreg == treg || rreg == treg)
+ g_assert_not_reached ();
+
+ if (ci->vtype_num) {
+ int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
+ x86_lea_membase (s->code, treg, X86_EBP, offset);
+ x86_push_reg (s->code, treg);
+ }
+
+ if (tree->left->op != MB_TERM_NOP) {
+ g_assert (lreg >= 0);
+ x86_push_reg (s->code, lreg);
+ }
- if (tree->data.i)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.i);
+ x86_call_reg (s->code, rreg);
+
+ if (ci->args_size)
+ x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
+ PRINT_REG ("CALL_I4", tree->reg1);
+
g_assert (tree->reg1 == X86_EAX);
}
+
+reg: CALL_I4 (this, LDIND_I4 (ADDR_G)) {
+ MethodCallInfo *ci = tree->data.ci;
+ int lreg = tree->left->reg1;
+ int treg = X86_EAX;
-reg: CALL_I4 (LDIND_I4 (ADDR_G)) {
+ if (lreg == treg)
+ treg = X86_EDX;
- x86_call_mem (s->code, tree->left->left->data.p);
+ if (ci->vtype_num) {
+ int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
+ x86_lea_membase (s->code, treg, X86_EBP, offset);
+ x86_push_reg (s->code, treg);
+ }
+
+ if (tree->left->op != MB_TERM_NOP) {
+ g_assert (lreg >= 0);
+ x86_push_reg (s->code, lreg);
+ }
+
+ x86_call_mem (s->code, tree->right->left->data.p);
+
+ if (ci->args_size)
+ x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
- if (tree->dat_.i)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.i);
+ PRINT_REG ("CALL_I4", tree->reg1);
g_assert (tree->reg1 == X86_EAX);
}
-reg: CALL_I4 (INTF_ADDR (reg)) {
- int reg1 = tree->left->left->reg1;
+reg: CALL_I4 (this, INTF_ADDR) {
+ MethodCallInfo *ci = tree->data.ci;
+ int lreg = tree->left->reg1;
+ int treg = X86_EAX;
- x86_mov_reg_membase (s->code, reg1, reg1, 0, 4);
- x86_mov_reg_membase (s->code, reg1, reg1,
+ if (lreg == treg)
+ treg = X86_EDX;
+
+ if (ci->vtype_num) {
+ int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
+ x86_lea_membase (s->code, treg, X86_EBP, offset);
+ x86_push_reg (s->code, treg);
+ }
+
+ if (tree->left->op != MB_TERM_NOP) {
+ g_assert (lreg >= 0);
+ x86_push_reg (s->code, lreg);
+ }
+
+ x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
+ x86_mov_reg_membase (s->code, lreg, lreg,
G_STRUCT_OFFSET (MonoClass, interface_offsets), 4);
- x86_mov_reg_membase (s->code, reg1, reg1, tree->left->data.m->klass->interface_id << 2, 4);
- x86_call_virtual (s->code, reg1, tree->left->data.m->slot << 2);
+ x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
+ x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
- if (tree->data.i)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.i);
+ if (ci->args_size)
+ x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
+ PRINT_REG ("CALL_I4(INTERFACE)", tree->reg1);
+
g_assert (tree->reg1 == X86_EAX);
}
+
+reg: CALL_I4 (this, VFUNC_ADDR) {
+ MethodCallInfo *ci = tree->data.ci;
+ int lreg = tree->left->reg1;
+ int treg = X86_EAX;
-reg: CALL_I4 (VFUNC_ADDR (reg)) {
- int reg1 = tree->left->left->reg1;
+ if (lreg == treg)
+ treg = X86_EDX;
+
+ if (ci->vtype_num) {
+ int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
+ x86_lea_membase (s->code, treg, X86_EBP, offset);
+ x86_push_reg (s->code, treg);
+ }
+
+ if (tree->left->op != MB_TERM_NOP) {
+ g_assert (lreg >= 0);
+ x86_push_reg (s->code, lreg);
+ }
- x86_mov_reg_membase (s->code, reg1, reg1, 0, 4);
- x86_call_virtual (s->code, reg1,
- G_STRUCT_OFFSET (MonoClass, vtable) + (tree->left->data.m->slot << 2));
+ x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
+ x86_call_virtual (s->code, lreg,
+ G_STRUCT_OFFSET (MonoClass, vtable) + (tree->right->data.m->slot << 2));
- if (tree->data.i)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.i);
+ if (ci->args_size)
+ x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
- PRINT_REG ("CONV_I4(VIRTUAL)", tree->reg1);
+ PRINT_REG ("CALL_I4(VIRTUAL)", tree->reg1);
g_assert (tree->reg1 == X86_EAX);
}
-stmt: CALL_I4 (LDIND_I4 (ADDR_G)) {
- x86_call_mem (s->code, tree->left->left->data.p);
+stmt: CALL_VOID (this, LDIND_I4 (ADDR_G)) {
+ MethodCallInfo *ci = tree->data.ci;
+ int lreg = tree->left->reg1;
+ int treg = X86_EAX;
- if (tree->data.i)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.i);
+ if (lreg == treg)
+ treg = X86_EDX;
+
+ if (ci->vtype_num) {
+ int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
+ x86_lea_membase (s->code, treg, X86_EBP, offset);
+ x86_push_reg (s->code, treg);
+ }
+
+ if (tree->left->op != MB_TERM_NOP) {
+ g_assert (lreg >= 0);
+ x86_push_reg (s->code, lreg);
+ }
+
+ x86_call_mem (s->code, tree->right->left->data.p);
+
+ if (ci->args_size)
+ x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
}
+
+stmt: CALL_VOID (this, INTF_ADDR) {
+ MethodCallInfo *ci = tree->data.ci;
+ int lreg = tree->left->reg1;
+ int treg = X86_EAX;
-stmt: CALL_I4 (INTF_ADDR (reg)) {
- int reg1 = tree->left->left->reg1;
+ if (lreg == treg)
+ treg = X86_EDX;
- 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->left->data.m->klass->interface_id << 2, 4);
- x86_call_virtual (s->code, reg1, tree->left->data.m->slot << 2);
+ if (ci->vtype_num) {
+ int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
+ x86_lea_membase (s->code, treg, X86_EBP, offset);
+ x86_push_reg (s->code, treg);
+ }
+
+ if (tree->left->op != MB_TERM_NOP) {
+ g_assert (lreg >= 0);
+ x86_push_reg (s->code, lreg);
+ }
- if (tree->data.i)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.i);
+ x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
+ x86_mov_reg_membase (s->code, lreg, lreg,
+ G_STRUCT_OFFSET (MonoClass, interface_offsets), 4);
+ x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
+ x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
+
+ if (ci->args_size)
+ x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
}
-stmt: CALL_I4 (VFUNC_ADDR (reg)) {
- int reg1 = tree->left->left->reg1;
+stmt: CALL_VOID (this, VFUNC_ADDR) {
+ MethodCallInfo *ci = tree->data.ci;
+ int lreg = tree->left->reg1;
+ int treg = X86_EAX;
- x86_mov_reg_membase (s->code, reg1, reg1, 0, 4);
- x86_call_virtual (s->code, reg1,
- G_STRUCT_OFFSET (MonoClass, vtable) + (tree->left->data.m->slot << 2));
+ if (lreg == treg)
+ treg = X86_EDX;
- if (tree->data.i)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.i);
+ if (ci->vtype_num) {
+ int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
+ x86_lea_membase (s->code, treg, X86_EBP, offset);
+ x86_push_reg (s->code, treg);
+ }
+
+ if (tree->left->op != MB_TERM_NOP) {
+ g_assert (lreg >= 0);
+ x86_push_reg (s->code, lreg);
+ }
+
+ x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
+ x86_call_virtual (s->code, lreg,
+ G_STRUCT_OFFSET (MonoClass, vtable) + (tree->right->data.m->slot << 2));
+
+ if (ci->args_size)
+ x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
}
stmt: SWITCH (reg) {
@@ -1416,12 +1566,29 @@
x86_pop_reg (s->code, X86_ECX);
}
-lreg: CALL_I8 (LDIND_I4 (ADDR_G)) {
+lreg: CALL_I8 (this, LDIND_I4 (ADDR_G)) {
+ MethodCallInfo *ci = tree->data.ci;
+ int lreg = tree->left->reg1;
+ int treg = X86_EAX;
+
+ if (lreg == treg)
+ treg = X86_EDX;
- x86_call_mem (s->code, tree->left->left->data.p);
+ if (ci->vtype_num) {
+ int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
+ x86_lea_membase (s->code, treg, X86_EBP, offset);
+ x86_push_reg (s->code, treg);
+ }
- if (tree->data.i)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.i);
+ if (tree->left->op != MB_TERM_NOP) {
+ g_assert (lreg >= 0);
+ x86_push_reg (s->code, lreg);
+ }
+
+ x86_call_mem (s->code, tree->right->left->data.p);
+
+ if (ci->args_size)
+ x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
g_assert (tree->reg1 == X86_EAX);
g_assert (tree->reg2 == X86_EDX);
@@ -1679,7 +1846,6 @@
freg: CONST_R8 {
double d = *(double *)tree->data.p;
- printf ("TEST %f\n", d);
if (d == 0.0)
x86_fldz (s->code);
@@ -1818,36 +1984,85 @@
x86_branch32 (s->code, X86_CC_NE, tree->data.bb->addr - offset, FALSE);
}
-freg: CALL_R8 (LDIND_I4 (ADDR_G)) {
+freg: CALL_R8 (this, LDIND_I4 (ADDR_G)) {
+ MethodCallInfo *ci = tree->data.ci;
+ int lreg = tree->left->reg1;
+ int treg = X86_EAX;
+
+ if (lreg == treg)
+ treg = X86_EDX;
- x86_call_mem (s->code, tree->left->left->data.p);
+ if (ci->vtype_num) {
+ int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
+ x86_lea_membase (s->code, treg, X86_EBP, offset);
+ x86_push_reg (s->code, treg);
+ }
- if (tree->data.i)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.i);
+ if (tree->left->op != MB_TERM_NOP) {
+ g_assert (lreg >= 0);
+ x86_push_reg (s->code, lreg);
+ }
+
+ x86_call_mem (s->code, tree->right->left->data.p);
+
+ if (ci->args_size)
+ x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
}
+
+freg: CALL_R8 (this, INTF_ADDR) {
+ MethodCallInfo *ci = tree->data.ci;
+ int lreg = tree->left->reg1;
+ int treg = X86_EAX;
-freg: CALL_R8 (INTF_ADDR (reg)) {
- int reg1 = tree->left->left->reg1;
+ if (lreg == treg)
+ treg = X86_EDX;
- x86_mov_reg_membase (s->code, reg1, reg1, 0, 4);
- x86_mov_reg_membase (s->code, reg1, reg1,
+ if (ci->vtype_num) {
+ int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
+ x86_lea_membase (s->code, treg, X86_EBP, offset);
+ x86_push_reg (s->code, treg);
+ }
+
+ if (tree->left->op != MB_TERM_NOP) {
+ g_assert (lreg >= 0);
+ x86_push_reg (s->code, lreg);
+ }
+
+ x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
+ x86_mov_reg_membase (s->code, lreg, lreg,
G_STRUCT_OFFSET (MonoClass, interface_offsets), 4);
- x86_mov_reg_membase (s->code, reg1, reg1, tree->left->data.m->klass->interface_id << 2, 4);
- x86_call_virtual (s->code, reg1, tree->left->data.m->slot << 2);
+ x86_mov_reg_membase (s->code, lreg, lreg, tree->right->data.m->klass->interface_id << 2, 4);
+ x86_call_virtual (s->code, lreg, tree->right->data.m->slot << 2);
- if (tree->data.i)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.i);
+ if (ci->args_size)
+ x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
}
+
+freg: CALL_R8 (this, VFUNC_ADDR) {
+ MethodCallInfo *ci = tree->data.ci;
+ int lreg = tree->left->reg1;
+ int treg = X86_EAX;
-freg: CALL_R8 (VFUNC_ADDR (reg)) {
- int reg1 = tree->left->left->reg1;
+ if (lreg == treg)
+ treg = X86_EDX;
+
+ if (ci->vtype_num) {
+ int offset = g_array_index (s->varinfo, MonoVarInfo, ci->vtype_num).offset;
+ x86_lea_membase (s->code, treg, X86_EBP, offset);
+ x86_push_reg (s->code, treg);
+ }
+
+ if (tree->left->op != MB_TERM_NOP) {
+ g_assert (lreg >= 0);
+ x86_push_reg (s->code, lreg);
+ }
- x86_mov_reg_membase (s->code, reg1, reg1, 0, 4);
- x86_call_virtual (s->code, reg1,
- G_STRUCT_OFFSET (MonoClass, vtable) + (tree->left->data.m->slot << 2));
+ x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
+ x86_call_virtual (s->code, lreg,
+ G_STRUCT_OFFSET (MonoClass, vtable) + (tree->right->data.m->slot << 2));
- if (tree->data.i)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.i);
+ if (ci->args_size)
+ x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, ci->args_size);
}
stmt: RETV (freg) {