#define MONO_EMIT_NEW_UNALU(cfg,op,dr,sr1) do { \
MonoInst *inst; \
- inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- inst->opcode = op; \
+ MONO_INST_NEW ((cfg), inst, op); \
inst->dreg = dr; \
inst->sreg1 = sr1; \
mono_bblock_add_inst (cfg->cbb, inst); \
#define MONO_EMIT_NEW_BIALU(cfg,op,dr,sr1,sr2) do { \
MonoInst *inst; \
- inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- inst->opcode = op; \
+ MONO_INST_NEW ((cfg), inst, op); \
inst->dreg = dr; \
inst->sreg1 = sr1; \
inst->sreg2 = sr2; \
#define MONO_EMIT_NEW_BIALU_IMM(cfg,op,dr,sr,imm) do { \
MonoInst *inst; \
- inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- inst->opcode = op; \
+ MONO_INST_NEW ((cfg), inst, op); \
inst->dreg = dr; \
inst->sreg1 = sr; \
inst->inst_p1 = (gpointer)(gssize)(imm); \
#define MONO_EMIT_NEW_LOAD_MEM(cfg,dr,addr) do { \
MonoInst *inst; \
- inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- inst->opcode = OP_LOADU4_MEM; \
+ MONO_INST_NEW ((cfg), inst, OP_LOADU4_MEM); \
inst->dreg = dr; \
inst->inst_p0 = addr; \
mono_bblock_add_inst (cfg->cbb, inst); \
#define MONO_EMIT_NEW_LOAD_MEMBASE(cfg,dr,base,offset) do { \
MonoInst *inst; \
- inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- inst->opcode = OP_LOAD_MEMBASE; \
+ MONO_INST_NEW ((cfg), inst, OP_LOAD_MEMBASE); \
inst->dreg = dr; \
inst->inst_basereg = base; \
inst->inst_offset = offset; \
#define MONO_EMIT_NEW_LOAD_MEMBASE_OP(cfg,op,dr,base,offset) do { \
MonoInst *inst; \
- inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- inst->opcode = op; \
+ MONO_INST_NEW ((cfg), inst, op); \
inst->dreg = dr; \
inst->inst_basereg = base; \
inst->inst_offset = offset; \
#define MONO_EMIT_NEW_STORE_MEMBASE(cfg,op,base,offset,sr) do { \
MonoInst *inst; \
- inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- inst->opcode = op; \
+ MONO_INST_NEW ((cfg), inst, op); \
inst->sreg1 = sr; \
inst->inst_destbasereg = base; \
inst->inst_offset = offset; \
#define MONO_EMIT_NEW_STORE_MEMBASE_IMM(cfg,op,base,offset,imm) do { \
MonoInst *inst; \
- inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- inst->opcode = op; \
+ MONO_INST_NEW ((cfg), inst, op); \
inst->inst_destbasereg = base; \
inst->inst_offset = offset; \
inst->inst_p1 = (gpointer)imm; \
#define MONO_EMIT_NEW_COMPARE_IMM(cfg,sr1,imm) do { \
MonoInst *inst; \
- inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- inst->opcode = OP_COMPARE_IMM; \
+ MONO_INST_NEW ((cfg), inst, OP_COMPARE_IMM); \
inst->sreg1 = sr1; \
inst->inst_p1 = (gpointer)imm; \
mono_bblock_add_inst ((cfg)->cbb, inst); \
#define MONO_EMIT_NEW_ICOMPARE_IMM(cfg,sr1,imm) do { \
MonoInst *inst; \
- inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- inst->opcode = sizeof (void*) == 8 ? OP_ICOMPARE_IMM : OP_COMPARE_IMM; \
+ MONO_INST_NEW ((cfg), inst, sizeof (void*) == 8 ? OP_ICOMPARE_IMM : OP_COMPARE_IMM); \
inst->sreg1 = sr1; \
inst->inst_p1 = (gpointer)imm; \
mono_bblock_add_inst ((cfg)->cbb, inst); \
#define MONO_EMIT_NEW_COND_EXC(cfg,cond,name) do { \
MonoInst *inst; \
- inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
+ MONO_INST_NEW ((cfg), inst, OP_NOP); \
inst->opcode = OP_COND_EXC_##cond; \
inst->inst_p1 = (char*)name; \
mono_bblock_add_inst ((cfg)->cbb, inst); \
#define MONO_EMIT_NEW_ICONST(cfg,dr,imm) do { \
MonoInst *inst; \
- inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- inst->opcode = OP_ICONST; \
+ MONO_INST_NEW ((cfg), inst, OP_ICONST); \
inst->dreg = dr; \
inst->inst_c0 = imm; \
mono_bblock_add_inst ((cfg)->cbb, inst); \
#define MONO_EMIT_NEW_I8CONST(cfg,dr,imm) do { \
MonoInst *inst; \
- inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- inst->opcode = OP_I8CONST; \
+ MONO_INST_NEW ((cfg), inst, OP_I8CONST); \
inst->dreg = dr; \
inst->inst_l = imm; \
mono_bblock_add_inst ((cfg)->cbb, inst); \
#define MONO_EMIT_NEW_PCONST(cfg,dr,imm) do { \
MonoInst *inst; \
- inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- inst->opcode = OP_ICONST; \
+ MONO_INST_NEW ((cfg), inst, OP_ICONST); \
inst->dreg = dr; \
inst->inst_p0 = (gpointer) imm; \
mono_bblock_add_inst ((cfg)->cbb, inst); \
#define MONO_EMIT_NEW_AOTCONST(cfg,dr,imm,type) do { \
MonoInst *inst; \
- inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- inst->opcode = OP_AOTCONST; \
+ MONO_INST_NEW ((cfg), inst, OP_AOTCONST); \
inst->dreg = dr; \
inst->inst_p0 = imm; \
inst->inst_c1 = type; \
MonoInst *target_label; \
target_label = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
target_label->opcode = OP_LABEL; \
- MONO_INST_LIST_ADD (&target_label->node, \
- &(targetbb)->ins_list); \
+ target_label->next = (targetbb)->code; \
+ (targetbb)->code = target_label; \
target_label->inst_c0 = (targetbb)->native_offset; \
- inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- inst->opcode = op; \
+ MONO_INST_NEW ((cfg), inst, op); \
inst->inst_i0 = target_label; \
inst->flags = MONO_INST_BRLABEL; \
mono_bblock_add_inst ((cfg)->cbb, inst); \
#define MONO_EMIT_NEW_BRANCH_LABEL(cfg,op,label) do { \
MonoInst *inst; \
- inst = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst)); \
- inst->opcode = op; \
+ MONO_INST_NEW ((cfg), inst, op); \
inst->inst_i0 = label; \
inst->flags = MONO_INST_BRLABEL; \
mono_bblock_add_inst ((cfg)->cbb, inst); \
* normal rules.
*/
MonoInst *inst;
- inst = mono_mempool_alloc0 (s->mempool, sizeof (MonoInst));
- inst->opcode = OP_ICONST; /* doesn't matter */
+ MONO_INST_NEW (s, inst, OP_NOP); /* The opcode doesn't matter */
inst->inst_basereg = state->reg1;
inst->inst_offset = 0;
state->tree = inst;
/* the backend must patch the address. we use 0xf0f0f0f0 to avoid the usage
* of special (short) opcodes on x86 */
if (sizeof (gpointer) == 8)
- MONO_EMIT_NEW_LOAD_MEMBASE (s, target_reg, offset_reg, (long)0xf0f0f0f0f0f0f0f1LL);
+ MONO_EMIT_NEW_LOAD_MEMBASE (s, target_reg, offset_reg, (gint64)0xf0f0f0f0f0f0f0f1LL);
else
MONO_EMIT_NEW_LOAD_MEMBASE (s, target_reg, offset_reg, 0xf0f0f0f0);
}
mini_emit_virtual_call (s, state, tree, OP_VCALL, OP_VCALL_MEMBASE);
}
+reg: OP_CALLVIRT_IMT (reg, reg) {
+ tree->opcode = OP_CALLVIRT;
+ mini_emit_virtual_imt_call (s, state, tree, OP_CALL, OP_CALL_MEMBASE, state->right->reg1);
+}
+
+stmt: OP_VOIDCALLVIRT_IMT (reg, reg) {
+ tree->opcode = OP_VOIDCALLVIRT;
+ mini_emit_virtual_imt_call (s, state, tree, OP_VOIDCALL, OP_VOIDCALL_MEMBASE, state->right->reg1);
+}
+
+freg: OP_FCALLVIRT_IMT (reg, reg) {
+ tree->opcode = OP_FCALLVIRT;
+ mini_emit_virtual_imt_call (s, state, tree, OP_FCALL, OP_FCALL_MEMBASE, state->right->reg1);
+}
+
+stmt: OP_VCALLVIRT_IMT (OP_GROUP (reg, reg), reg) {
+ int imt_reg = state->left->right->reg1;
+ tree->opcode = OP_VCALLVIRT;
+ tree->inst_left = tree->inst_left->inst_left;
+ state->left = state->left->left;
+ mini_emit_virtual_imt_call (s, state, tree, OP_VCALL, OP_VCALL_MEMBASE, imt_reg);
+}
+
reg: OP_CALL_REG (reg) {
tree->sreg1 = state->left->reg1;
tree->dreg = state->reg1;
mono_bblock_add_inst (s->cbb, tree);
}
+reg: OP_CHECK_THIS_PASSTHROUGH (reg) {
+ MonoInst *check;
+
+ MONO_INST_NEW (s, check, OP_CHECK_THIS);
+ check->sreg1 = state->left->reg1;
+ mono_bblock_add_inst (s->cbb, check);
+
+ MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, state->left->reg1);
+}
+
# object related opcodes
reg: CEE_ISINST (reg) {
MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, obj_reg);
}
+reg: OP_UNBOXCAST_REG (reg, reg) {
+ int obj_reg = state->left->reg1;
+ int element_klass_reg = state->right->reg1;
+ int vtable_reg = mono_regstate_next_int (s->rs);
+ int klass_reg = mono_regstate_next_int (s->rs);
+ int eclass_reg = mono_regstate_next_int (s->rs);
+ int rank_reg = mono_regstate_next_int (s->rs);
+
+ MONO_EMIT_NEW_LOAD_MEMBASE (s, vtable_reg, obj_reg, G_STRUCT_OFFSET (MonoObject, vtable));
+ MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADU1_MEMBASE, rank_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, rank));
+
+ // Check rank == 0
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, rank_reg, 0, "InvalidCastException");
+
+ MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass));
+ MONO_EMIT_NEW_LOAD_MEMBASE (s, eclass_reg, klass_reg, G_STRUCT_OFFSET (MonoClass, element_class));
+
+ MONO_EMIT_NEW_COMPARE_EXC (s, NE_UN, eclass_reg, element_klass_reg, "InvalidCastException");
+
+ MONO_EMIT_UNALU (s, tree, OP_MOVE, state->reg1, obj_reg);
+}
+
reg: CEE_CASTCLASS (reg) {
MonoClass *klass = tree->inst_newa_class;
MonoInst *object_is_null;
MonoInst *end_label, *fail_label, *no_proxy_label, *ok_result_label;
int obj_reg = state->left->reg1;
int tmp_reg = mono_regstate_next_int (s->rs);
+ int tmp2_reg = mono_regstate_next_int (s->rs);
int klass_reg = mono_regstate_next_int (s->rs);
MONO_NEW_LABEL (s, end_label);
MONO_EMIT_NEW_COMPARE_IMM_EXC (s, NE_UN, klass_reg, mono_defaults.transparent_proxy_class, "InvalidCastException");
}
-
- MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, remote_class));
- MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, tmp_reg, G_STRUCT_OFFSET (MonoRemoteClass, proxy_class));
-
- MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info));
- MONO_EMIT_NEW_COMPARE_IMM_EXC (s, EQ, tmp_reg, 0, "InvalidCastException");
+ MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp2_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info));
+ MONO_EMIT_NEW_COMPARE_IMM_EXC (s, EQ, tmp2_reg, 0, "InvalidCastException");
MONO_EMIT_NEW_ICONST (s, state->reg1, 1);
MONO_EMIT_NEW_BRANCH_LABEL (s, OP_BR, end_label);
MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, remote_class));
MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, tmp_reg, G_STRUCT_OFFSET (MonoRemoteClass, proxy_class));
- MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info));
- MONO_EMIT_NEW_COMPARE_IMM_BRANCH_LABEL (s, CEE_BEQ, tmp_reg, 0, no_proxy_label);
+ MONO_EMIT_NEW_LOAD_MEMBASE (s, tmp2_reg, obj_reg, G_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info));
+ MONO_EMIT_NEW_COMPARE_IMM_BRANCH_LABEL (s, CEE_BEQ, tmp2_reg, 0, no_proxy_label);
mini_emit_isinst (s, klass_reg, klass, fail_label, ok_result_label);
mono_bblock_add_inst (s->cbb, fail_label);
MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, state->left->reg1, G_STRUCT_OFFSET (MonoTypedRef, value));
}
+reg: OP_REFANYVAL_REG (reg, reg) {
+ int klass_reg = mono_regstate_next_int (s->rs);
+ g_assert (!s->compile_aot);
+ MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, state->left->reg1, G_STRUCT_OFFSET (MonoTypedRef, klass));
+ MONO_EMIT_NEW_COMPARE_EXC (s, NE_UN, klass_reg, state->right->reg1, "InvalidCastException");
+ MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, state->left->reg1, G_STRUCT_OFFSET (MonoTypedRef, value));
+}
+
reg: OP_REFANYTYPE (reg) {
MONO_EMIT_NEW_LOAD_MEMBASE (s, state->reg1, state->left->reg1, G_STRUCT_OFFSET (MonoTypedRef, type));
}
MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREP_MEMBASE_REG, state->right->reg1, G_STRUCT_OFFSET (MonoTypedRef, value), state->left->left->reg1);
}
-reg: OP_MIN (reg, reg) "2" {
- /* min (x,y) = y + (((x-y)>>31)&(x-y)); */
- int diff = mono_regstate_next_int (s->rs);
- int shifted = mono_regstate_next_int (s->rs);
- int anded = mono_regstate_next_int (s->rs);
- MONO_EMIT_NEW_BIALU (s, CEE_SUB, diff, state->left->reg1, state->right->reg1);
- MONO_EMIT_NEW_BIALU_IMM (s, OP_SHR_IMM, shifted, diff, (sizeof(void*)*8-1));
- MONO_EMIT_NEW_BIALU (s, CEE_AND, anded, shifted, diff);
- MONO_EMIT_NEW_BIALU (s, CEE_ADD, state->reg1, anded, state->right->reg1);
-}
-
-reg: OP_MAX (reg, reg) "2" {
- /* max (x,y) = x - (((x-y)>>31)&(x-y)); */
- int diff = mono_regstate_next_int (s->rs);
- int shifted = mono_regstate_next_int (s->rs);
- int anded = mono_regstate_next_int (s->rs);
- MONO_EMIT_NEW_BIALU (s, CEE_SUB, diff, state->left->reg1, state->right->reg1);
- MONO_EMIT_NEW_BIALU_IMM (s, OP_SHR_IMM, shifted, diff, (sizeof(void*)*8-1));
- MONO_EMIT_NEW_BIALU (s, CEE_AND, anded, shifted, diff);
- MONO_EMIT_NEW_BIALU (s, CEE_SUB, state->reg1, state->left->reg1, anded);
+stmt: OP_MKREFANY_REGS (OP_GROUP (reg, reg), OP_GROUP (reg, reg)) {
+ g_assert (!s->compile_aot);
+ MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREP_MEMBASE_REG,
+ state->right->right->reg1, G_STRUCT_OFFSET (MonoTypedRef, type), state->left->left->reg1);
+ MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREP_MEMBASE_REG,
+ state->right->right->reg1, G_STRUCT_OFFSET (MonoTypedRef, klass), state->left->right->reg1);
+ MONO_EMIT_NEW_STORE_MEMBASE (s, OP_STOREP_MEMBASE_REG,
+ state->right->right->reg1, G_STRUCT_OFFSET (MonoTypedRef, value), state->right->left->reg1);
}
%%
/* Emit code which loads interface_offsets [klass->interface_id]
* The array is stored in memory before vtable.
*/
-#ifndef MONO_ARCH_HAVE_IMT
static void
mini_emit_load_intf_reg_vtable (MonoCompile *s, int intf_reg, int vtable_reg, MonoClass *klass)
{
MONO_EMIT_NEW_LOAD_MEMBASE (s, intf_reg, vtable_reg, -((klass->interface_id + 1) * SIZEOF_VOID_P));
}
}
-#endif
/*
* Emit code which loads into "intf_bit_reg" a nonzero value if the MonoClass
#ifdef MONO_ARCH_HAVE_IMT
static void
-emit_imt_argument (MonoCompile *cfg, MonoCallInst *call) {
+emit_imt_argument (MonoCompile *cfg, MonoCallInst *call, gboolean have_imt_arg, int imt_reg) {
#ifdef MONO_ARCH_IMT_REG
int method_reg = mono_regstate_next_int (cfg->rs);
if (cfg->compile_aot) {
+ g_assert (!have_imt_arg);
MONO_EMIT_NEW_AOTCONST (cfg, method_reg, call->method, MONO_PATCH_INFO_METHODCONST);
} else {
- MonoInst *inst;
- MONO_INST_NEW (cfg, inst, OP_PCONST);
- inst->inst_p0 = call->method;
- inst->dreg = method_reg;
- mono_bblock_add_inst (cfg->cbb, inst);
+ if (have_imt_arg) {
+ MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, method_reg, imt_reg);
+ } else {
+ MonoInst *inst;
+ MONO_INST_NEW (cfg, inst, OP_PCONST);
+ inst->inst_p0 = call->method;
+ inst->dreg = method_reg;
+ mono_bblock_add_inst (cfg->cbb, inst);
+ }
}
mono_call_inst_add_outarg_reg (cfg, call, method_reg, MONO_ARCH_IMT_REG, FALSE);
#endif
static void
-mini_emit_virtual_call (MonoCompile *cfg, void *st, MonoInst *tree, int novirtop, int virtop)
+mini_emit_virtual_call_internal (MonoCompile *cfg, void *st, MonoInst *tree, int novirtop, int virtop,
+ gboolean have_imt_arg, int imt_reg)
{
MonoMethod *method = ((MonoCallInst*)tree)->method;
int vtable_reg, slot_reg, this_reg;
MBState *state = st;
+ int slot;
this_reg = state->left->reg1;
mono_arch_emit_this_vret_args (cfg, (MonoCallInst*)tree, this_reg, state->left->tree->type, novirtop == OP_VCALL? state->right->reg1: -1);
return;
}
- /* Initialize method->slot */
- mono_class_setup_vtable (method->klass);
+ if (method->klass->generic_class && !method->klass->vtable) {
+ MonoMethod *gmethod = mono_method_get_declaring_generic_method (method);
+ mono_class_setup_vtable (gmethod->klass);
+
+ slot = gmethod->slot;
+ g_assert (slot != -1);
+ } else {
+ /* Initialize method->slot */
+ mono_class_setup_vtable (method->klass);
+ slot = method->slot;
+ }
vtable_reg = mono_regstate_next_int (cfg->rs);
MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, this_reg, G_STRUCT_OFFSET (MonoObject, vtable));
if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+ slot_reg = -1;
#ifdef MONO_ARCH_HAVE_IMT
- guint32 imt_slot = mono_method_get_imt_slot (method);
- emit_imt_argument (cfg, (MonoCallInst*)tree);
- slot_reg = vtable_reg;
- tree->inst_offset = ((gint32)imt_slot - MONO_IMT_SIZE) * SIZEOF_VOID_P;
-#else
- slot_reg = mono_regstate_next_int (cfg->rs);
- mini_emit_load_intf_reg_vtable (cfg, slot_reg, vtable_reg, method->klass);
- tree->inst_offset = method->slot * SIZEOF_VOID_P;
+ if (mono_use_imt) {
+ guint32 imt_slot = mono_method_get_imt_slot (method);
+ emit_imt_argument (cfg, (MonoCallInst*)tree, have_imt_arg, imt_reg);
+ slot_reg = vtable_reg;
+ tree->inst_offset = ((gint32)imt_slot - MONO_IMT_SIZE) * SIZEOF_VOID_P;
+ }
#endif
+ if (slot_reg == -1) {
+ g_assert (!have_imt_arg);
+ slot_reg = mono_regstate_next_int (cfg->rs);
+ mini_emit_load_intf_reg_vtable (cfg, slot_reg, vtable_reg, method->klass);
+ tree->inst_offset = slot * SIZEOF_VOID_P;
+ }
} else {
slot_reg = vtable_reg;
- tree->inst_offset = G_STRUCT_OFFSET (MonoVTable, vtable) + (method->slot * SIZEOF_VOID_P);
+ tree->inst_offset = G_STRUCT_OFFSET (MonoVTable, vtable) + (slot * SIZEOF_VOID_P);
}
tree->dreg = state->reg1;
mono_bblock_add_inst (cfg->cbb, tree);
}
+static void
+mini_emit_virtual_call (MonoCompile *cfg, void *st, MonoInst *tree, int novirtop, int virtop)
+{
+ mini_emit_virtual_call_internal (cfg, st, tree, novirtop, virtop, FALSE, -1);
+}
+
+static void
+mini_emit_virtual_imt_call (MonoCompile *cfg, void *st, MonoInst *tree, int novirtop, int virtop, int imt_reg)
+{
+ mini_emit_virtual_call_internal (cfg, st, tree, novirtop, virtop, TRUE, imt_reg);
+}
+
static void
emit_rgctx_argument (MonoCompile *s, MonoInst *tree, int reg, int new_opcode)
{
MonoInst *dest, *pinfo;
int got_var_reg;
- dest = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst));
- dest->opcode = OP_GOT_ENTRY;
-
g_assert (cfg->got_var);
pinfo = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));
got_var_reg = cfg->got_var->dreg;
}
- dest = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoInst));
- dest->opcode = OP_GOT_ENTRY;
+ MONO_INST_NEW ((cfg), dest, OP_GOT_ENTRY);
dest->inst_left = cfg->got_var; /* not used */
dest->inst_right = pinfo;