MonoClass *klass;
MonoClassField *field;
X86AddressInfo ainfo;
- MonoJitCallInfo ci;
MonoJitFieldInfo fi;
MonoJitBranchInfo bi;
+ union {
+ gint32 size;
+ gint32 align;
+ } size_info;
} data;
};
x86_call_code (s->code, 0); \
} while (0);
+#define X86_CALL_END \
+ if (s->frame_size) { \
+ x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, s->frame_size); \
+ s->frame_size = 0; \
+ }
+
+#define X86_CALL_BEGIN \
+ if (tree->left->op != MB_TERM_NOP) { \
+ s->frame_size += 4; \
+ mono_assert (lreg >= 0); \
+ x86_push_reg (s->code, lreg); \
+ x86_alu_membase_imm (s->code, X86_CMP, lreg, 0, 0); \
+ } \
+ if (tree->data.i) { \
+ int offset = VARINFO (s, tree->data.i).offset; \
+ s->frame_size += 4; \
+ x86_lea_membase (s->code, treg, X86_EBP, offset); \
+ x86_push_reg (s->code, treg); \
+ }
+
/* we use this macro to move one lreg to another - source and
destination may overlap, but the register allocator has to
make sure that ((d1 < d2) && (s1 < s2))
stmt: ARG_I4 (LDIND_I4 (addr)) {
MBTree *at = tree->left->left;
+ s->frame_size += 4;
+
switch (at->data.ainfo.amode) {
case AMImmediate:
stmt: ARG_I4 (LDIND_I4 (ADDR_L)) {
int treg = VARINFO (s, tree->left->left->data.i).reg;
+ s->frame_size += 4;
x86_push_reg (s->code, treg);
} cost {
MBCOND ((VARINFO (data, tree->left->left->data.i).reg >= 0));
}
stmt: ARG_I4 (reg) {
+ s->frame_size += 4;
x86_push_reg (s->code, tree->left->reg1);
PRINT_REG ("ARG_I4", tree->left->reg1);
}
stmt: ARG_I4 (ADDR_G) {
+ s->frame_size += 4;
x86_push_imm (s->code, tree->left->data.p);
}
stmt: ARG_I4 (CONST_I4) "MB_USE_OPT1(0)" {
+ s->frame_size += 4;
x86_push_imm (s->code, tree->left->data.i);
}
if (lreg == treg || rreg == treg)
mono_assert_not_reached ();
- if (tree->left->op != MB_TERM_NOP) {
- mono_assert (lreg >= 0);
- x86_push_reg (s->code, lreg);
- x86_alu_membase_imm (s->code, X86_CMP, lreg, 0, 0);
- }
-
- if (tree->data.ci.vtype_num) {
- int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
- x86_lea_membase (s->code, treg, X86_EBP, offset);
- x86_push_reg (s->code, treg);
- }
+ X86_CALL_BEGIN
x86_call_reg (s->code, rreg);
- if (tree->data.ci.args_size)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
-
- PRINT_REG ("CALL_I4", tree->reg1);
+ X86_CALL_END
mono_assert (tree->reg1 == X86_EAX);
}
if (lreg == treg)
treg = X86_EDX;
- if (tree->left->op != MB_TERM_NOP) {
- mono_assert (lreg >= 0);
- x86_push_reg (s->code, lreg);
- x86_alu_membase_imm (s->code, X86_CMP, lreg, 0, 0);
- }
-
- if (tree->data.ci.vtype_num) {
- int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
- x86_lea_membase (s->code, treg, X86_EBP, offset);
- x86_push_reg (s->code, treg);
- }
+ X86_CALL_BEGIN
mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, tree->right->data.p);
x86_call_code (s->code, 0);
- if (tree->data.ci.args_size)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
-
- PRINT_REG ("CALL_I4", tree->reg1);
+ X86_CALL_END
mono_assert (tree->reg1 == X86_EAX);
}
if (lreg == treg)
treg = X86_EDX;
- if (tree->left->op != MB_TERM_NOP) {
- mono_assert (lreg >= 0);
- x86_push_reg (s->code, lreg);
- }
-
- if (tree->data.ci.vtype_num) {
- int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
- x86_lea_membase (s->code, treg, X86_EBP, offset);
- x86_push_reg (s->code, treg);
- }
+ X86_CALL_BEGIN
x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
x86_mov_reg_membase (s->code, lreg, lreg,
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.ci.args_size)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
-
- PRINT_REG ("CALL_I4(INTERFACE)", tree->reg1);
+ X86_CALL_END
mono_assert (tree->reg1 == X86_EAX);
}
if (lreg == treg)
treg = X86_EDX;
- if (tree->left->op != MB_TERM_NOP) {
- mono_assert (lreg >= 0);
- x86_push_reg (s->code, lreg);
- }
-
- if (tree->data.ci.vtype_num) {
- int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
- x86_lea_membase (s->code, treg, X86_EBP, offset);
- x86_push_reg (s->code, treg);
- }
+ X86_CALL_BEGIN
x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
x86_call_virtual (s->code, lreg,
G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
- if (tree->data.ci.args_size)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
-
- PRINT_REG ("CALL_I4(VIRTUAL)", tree->reg1);
+ X86_CALL_END
mono_assert (tree->reg1 == X86_EAX);
}
if (lreg == treg)
treg = X86_EDX;
- if (tree->left->op != MB_TERM_NOP) {
- mono_assert (lreg >= 0);
- x86_push_reg (s->code, lreg);
- x86_alu_membase_imm (s->code, X86_CMP, lreg, 0, 0);
- }
-
- if (tree->data.ci.vtype_num) {
- int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
- x86_lea_membase (s->code, treg, X86_EBP, offset);
- x86_push_reg (s->code, treg);
- }
+ X86_CALL_BEGIN
mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, tree->right->data.p);
x86_call_code (s->code, 0);
- if (tree->data.ci.args_size)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
+ X86_CALL_END
}
stmt: CALL_VOID (this, reg) {
if (lreg == treg || rreg == treg)
mono_assert_not_reached ();
- if (tree->left->op != MB_TERM_NOP) {
- mono_assert (lreg >= 0);
- x86_push_reg (s->code, lreg);
- x86_alu_membase_imm (s->code, X86_CMP, lreg, 0, 0);
- }
-
- if (tree->data.ci.vtype_num) {
- int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
- x86_lea_membase (s->code, treg, X86_EBP, offset);
- x86_push_reg (s->code, treg);
- }
+ X86_CALL_BEGIN
x86_call_reg (s->code, tree->right->reg1);
- if (tree->data.ci.args_size)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
+ X86_CALL_END
}
stmt: CALL_VOID (this, INTF_ADDR) {
if (lreg == treg)
treg = X86_EDX;
- if (tree->left->op != MB_TERM_NOP) {
- mono_assert (lreg >= 0);
- x86_push_reg (s->code, lreg);
- }
-
- if (tree->data.ci.vtype_num) {
- int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
- x86_lea_membase (s->code, treg, X86_EBP, offset);
- x86_push_reg (s->code, treg);
- }
+ X86_CALL_BEGIN
x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
x86_mov_reg_membase (s->code, lreg, lreg,
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.ci.args_size)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
+ X86_CALL_END
}
stmt: CALL_VOID (this, VFUNC_ADDR) {
if (lreg == treg)
treg = X86_EDX;
- if (tree->left->op != MB_TERM_NOP) {
- mono_assert (lreg >= 0);
- x86_push_reg (s->code, lreg);
- }
-
- if (tree->data.ci.vtype_num) {
- int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
- x86_lea_membase (s->code, treg, X86_EBP, offset);
- x86_push_reg (s->code, treg);
- }
+ X86_CALL_BEGIN
x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
x86_call_virtual (s->code, lreg,
G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
- if (tree->data.ci.args_size)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
+ X86_CALL_END
}
stmt: SWITCH (reg) {
if (lreg == treg || rreg == treg)
mono_assert_not_reached ();
- if (tree->left->op != MB_TERM_NOP) {
- mono_assert (lreg >= 0);
- x86_push_reg (s->code, lreg);
- x86_alu_membase_imm (s->code, X86_CMP, lreg, 0, 0);
- }
-
- if (tree->data.ci.vtype_num) {
- int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
- x86_lea_membase (s->code, treg, X86_EBP, offset);
- x86_push_reg (s->code, treg);
- }
+ X86_CALL_BEGIN
x86_call_reg (s->code, rreg);
- if (tree->data.ci.args_size)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
-
- PRINT_REG ("CALL_I8", tree->reg1);
+ X86_CALL_END
mono_assert (tree->reg1 == X86_EAX);
mono_assert (tree->reg2 == X86_EDX);
if (lreg == treg)
treg = X86_EDX;
- if (tree->left->op != MB_TERM_NOP) {
- mono_assert (lreg >= 0);
- x86_push_reg (s->code, lreg);
- x86_alu_membase_imm (s->code, X86_CMP, lreg, 0, 0);
- }
-
- if (tree->data.ci.vtype_num) {
- int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
- x86_lea_membase (s->code, treg, X86_EBP, offset);
- x86_push_reg (s->code, treg);
- }
+ X86_CALL_BEGIN
mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, tree->right->data.p);
x86_call_code (s->code, 0);
- if (tree->data.ci.args_size)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
+ X86_CALL_END
mono_assert (tree->reg1 == X86_EAX);
mono_assert (tree->reg2 == X86_EDX);
if (lreg == treg)
treg = X86_EDX;
- if (tree->left->op != MB_TERM_NOP) {
- mono_assert (lreg >= 0);
- x86_push_reg (s->code, lreg);
- }
-
- if (tree->data.ci.vtype_num) {
- int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
- x86_lea_membase (s->code, treg, X86_EBP, offset);
- x86_push_reg (s->code, treg);
- }
+ X86_CALL_BEGIN
x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
x86_call_virtual (s->code, lreg,
G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
- if (tree->data.ci.args_size)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
-
- PRINT_REG ("CALL0_I8(VIRTUAL)", tree->reg1);
- PRINT_REG ("CALL1_I8(VIRTUAL)", tree->reg2);
+ X86_CALL_END
mono_assert (tree->reg1 == X86_EAX);
mono_assert (tree->reg2 == X86_EDX);
if (lreg == treg)
treg = X86_EDX;
- if (tree->left->op != MB_TERM_NOP) {
- mono_assert (lreg >= 0);
- x86_push_reg (s->code, lreg);
- }
-
- if (tree->data.ci.vtype_num) {
- int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
- x86_lea_membase (s->code, treg, X86_EBP, offset);
- x86_push_reg (s->code, treg);
- }
+ X86_CALL_BEGIN
x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
x86_mov_reg_membase (s->code, lreg, lreg,
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.ci.args_size)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
-
- PRINT_REG ("CALL_I8(INTERFACE)", tree->reg1);
+ X86_CALL_END
mono_assert (tree->reg1 == X86_EAX);
mono_assert (tree->reg2 == X86_EDX);
stmt: ARG_I8 (lreg) {
+ s->frame_size += 8;
x86_push_reg (s->code, tree->left->reg2);
x86_push_reg (s->code, tree->left->reg1);
}
}
stmt: ARG_R4 (freg) {
+ s->frame_size += 4;
x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 4);
x86_fst_membase (s->code, X86_ESP, 0, FALSE, TRUE);
}
stmt: ARG_R8 (freg) {
+ s->frame_size += 8;
x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, 8);
x86_fst_membase (s->code, X86_ESP, 0, TRUE, TRUE);
}
if (lreg == treg || rreg == treg)
mono_assert_not_reached ();
- if (tree->left->op != MB_TERM_NOP) {
- mono_assert (lreg >= 0);
- x86_push_reg (s->code, lreg);
- x86_alu_membase_imm (s->code, X86_CMP, lreg, 0, 0);
- }
-
- if (tree->data.ci.vtype_num) {
- int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
- x86_lea_membase (s->code, treg, X86_EBP, offset);
- x86_push_reg (s->code, treg);
- }
+ X86_CALL_BEGIN
x86_call_reg (s->code, rreg);
- if (tree->data.ci.args_size)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
+ X86_CALL_END
}
freg: CALL_R8 (this, ADDR_G) {
if (lreg == treg)
treg = X86_EDX;
- if (tree->left->op != MB_TERM_NOP) {
- mono_assert (lreg >= 0);
- x86_push_reg (s->code, lreg);
- x86_alu_membase_imm (s->code, X86_CMP, lreg, 0, 0);
- }
-
- if (tree->data.ci.vtype_num) {
- int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
- x86_lea_membase (s->code, treg, X86_EBP, offset);
- x86_push_reg (s->code, treg);
- }
+ X86_CALL_BEGIN
mono_add_jump_info (s, s->code, MONO_JUMP_INFO_ABS, tree->right->data.p);
x86_call_code (s->code, 0);
- if (tree->data.ci.args_size)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
+ X86_CALL_END
}
freg: CALL_R8 (this, INTF_ADDR) {
if (lreg == treg)
treg = X86_EDX;
- if (tree->left->op != MB_TERM_NOP) {
- mono_assert (lreg >= 0);
- x86_push_reg (s->code, lreg);
- }
-
- if (tree->data.ci.vtype_num) {
- int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
- x86_lea_membase (s->code, treg, X86_EBP, offset);
- x86_push_reg (s->code, treg);
- }
+ X86_CALL_BEGIN
x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
x86_mov_reg_membase (s->code, lreg, lreg,
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.ci.args_size)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
+ X86_CALL_END
}
freg: CALL_R8 (this, VFUNC_ADDR) {
if (lreg == treg)
treg = X86_EDX;
- if (tree->left->op != MB_TERM_NOP) {
- mono_assert (lreg >= 0);
- x86_push_reg (s->code, lreg);
- }
-
- if (tree->data.ci.vtype_num) {
- int offset = VARINFO (s, tree->data.ci.vtype_num).offset;
- x86_lea_membase (s->code, treg, X86_EBP, offset);
- x86_push_reg (s->code, treg);
- }
+ X86_CALL_BEGIN
x86_mov_reg_membase (s->code, lreg, lreg, 0, 4);
x86_call_virtual (s->code, lreg,
G_STRUCT_OFFSET (MonoVTable, vtable) + (tree->right->data.m->slot << 2));
- if (tree->data.ci.args_size)
- x86_alu_reg_imm (s->code, X86_ADD, X86_ESP, tree->data.ci.args_size);
+ X86_CALL_END
}
stmt: RET (freg) {
}
stmt: ARG_OBJ (CONST_I4) {
+ s->frame_size += 4;
x86_push_imm (s->code, tree->left->data.i);
}
stmt: ARG_OBJ (reg) {
- int size = tree->data.i;
+ int pad;
+ int size = tree->data.size_info.size;
+ int align = tree->data.size_info.align;
int sa;
if (!size)
return;
- sa = size + 3;
- sa &= ~3;
+ g_assert ((align & 3) == 0);
+
+ pad = (align - ((s->frame_size + size) & (align -1))) & (align - 1);
+
+ sa = size + pad;
+
+ s->frame_size += sa;
+
+ g_assert ((s->frame_size & (align - 1)) == 0);
/* reserve space for the argument */
x86_alu_reg_imm (s->code, X86_SUB, X86_ESP, sa);