stmt: OP_NOT_REACHED {
}
+stmt: OP_MEMORY_BARRIER {
+ mono_bblock_add_inst (s->cbb, tree);
+}
+
#
# load/store operations
#
* Currently, we allways rethrow the abort exception, despite the fact
* that this is not correct. See thread6.cs for an example. But propagating
* the abort exception is more important than getting the sematics right.
- */
+ */
MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, state->left->reg1, 0);
MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BEQ, dont_throw);
MONO_EMIT_UNALU (s, tree, CEE_THROW, -1, state->left->reg1);
/* the object_is_null target simply copies the input register to the output */
mini_emit_isninst_cast (s, eclass_reg, klass->cast_class, false_label, object_is_null);
}
+ } else if (mono_class_is_nullable (klass)) {
+ MONO_EMIT_NEW_LOAD_MEMBASE (s, klass_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, klass));
+ /* the object_is_null target simply copies the input register to the output */
+ mini_emit_isninst_cast (s, klass_reg, klass->cast_class, false_label, object_is_null);
} else {
if (!s->compile_aot && !(s->opt & MONO_OPT_SHARED) && (klass->flags & TYPE_ATTRIBUTE_SEALED)) {
/* the remoting code is broken, access the class for now */
1) if the object is not instance of the class,
2) if the object is a proxy whose type cannot be determined */
- MonoClass *klass = tree->inst_newa_class;
+ MonoClass *klass = tree->inst_newa_class;
MonoInst *end_label, *true_label, *false_label, *false2_label;
MonoInst *no_proxy_label, *interface_fail_label;
int obj_reg = state->left->reg1;
#
# string support
#
-reg: OP_GETCHR (reg, reg) {
+reg: OP_GETCHR (reg, reg) "4" {
int mult_reg = mono_regstate_next_int (s->rs);
int add_reg = mono_regstate_next_int (s->rs);
MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADU2_MEMBASE, state->reg1, state->left->reg1, ind);
}
+reg: OP_STR_CHAR_ADDR (reg, reg) "4" {
+ int mult_reg = mono_regstate_next_int (s->rs);
+ int add_reg = mono_regstate_next_int (s->rs);
+
+ /*
+ * The corlib functions check for oob already.
+ * MONO_EMIT_BOUNDS_CHECK (s, state->left->reg1, MonoString, length, state->right->reg1);
+ */
+ MONO_EMIT_NEW_BIALU_IMM (s, OP_SHL_IMM, mult_reg, state->right->reg1, 1);
+ MONO_EMIT_NEW_BIALU (s, CEE_ADD, add_reg, mult_reg, state->left->reg1);
+ MONO_EMIT_BIALU_IMM (s, tree, OP_ADD_IMM, state->reg1, add_reg, G_STRUCT_OFFSET (MonoString, chars));
+}
+
reg: OP_STRLEN (reg) {
MONO_EMIT_LOAD_MEMBASE_OP (s, tree, OP_LOADI4_MEMBASE, state->reg1,
state->left->reg1, G_STRUCT_OFFSET (MonoString, length));
int iid_reg = mono_regstate_next_int (s->rs);
MONO_EMIT_NEW_AOTCONST (s, iid_reg, klass, MONO_PATCH_INFO_IID);
MONO_EMIT_NEW_BIALU (s, OP_COMPARE, -1, max_iid_reg, iid_reg);
- }
- else
+ } else {
MONO_EMIT_NEW_BIALU_IMM (s, OP_COMPARE_IMM, -1, max_iid_reg, klass->interface_id);
+ }
if (false_target)
MONO_EMIT_NEW_BRANCH_LABEL (s, CEE_BLT_UN, false_target);
else
mini_emit_max_iid_check (s, max_iid_reg, klass, false_target);
}
+/* Emit code which loads interface_offsets [klass->interface_id]
+ * The array is stored in memory before vtable.
+ */
static void
-mini_emit_load_intf_reg (MonoCompile *s, int intf_reg, int ioffset_reg, MonoClass *klass)
+mini_emit_load_intf_reg_vtable (MonoCompile *s, int intf_reg, int vtable_reg, MonoClass *klass)
{
if (s->compile_aot) {
+ int ioffset_reg = mono_regstate_next_int (s->rs);
int iid_reg = mono_regstate_next_int (s->rs);
+ int adjiid_reg = mono_regstate_next_int (s->rs);
MONO_EMIT_NEW_AOTCONST (s, iid_reg, klass, MONO_PATCH_INFO_IID);
+ /* Consider having it already adjusted with a new AOT const,
+ * so we avoid both the inc and the shift.
+ */
+ MONO_EMIT_NEW_BIALU (s, OP_ADD_IMM, adjiid_reg, iid_reg, 1);
#if SIZEOF_VOID_P == 8
- MONO_EMIT_NEW_BIALU_IMM (s, OP_SHL_IMM, iid_reg, iid_reg, 3);
+ MONO_EMIT_NEW_BIALU_IMM (s, OP_SHL_IMM, ioffset_reg, adjiid_reg, 3);
#else
- MONO_EMIT_NEW_BIALU_IMM (s, OP_SHL_IMM, iid_reg, iid_reg, 2);
+ MONO_EMIT_NEW_BIALU_IMM (s, OP_SHL_IMM, ioffset_reg, adjiid_reg, 2);
#endif
- MONO_EMIT_NEW_BIALU (s, CEE_ADD, ioffset_reg, ioffset_reg, iid_reg);
MONO_EMIT_NEW_LOAD_MEMBASE (s, intf_reg, ioffset_reg, 0);
+ } else {
+ MONO_EMIT_NEW_LOAD_MEMBASE (s, intf_reg, vtable_reg, -((klass->interface_id + 1) * SIZEOF_VOID_P));
}
- else
- MONO_EMIT_NEW_LOAD_MEMBASE (s, intf_reg, ioffset_reg, klass->interface_id * SIZEOF_VOID_P);
-}
-
-/* Emit code which loads <vtable_reg>->interface_offsets [klass->interface_id] */
-static void
-mini_emit_load_intf_reg_vtable (MonoCompile *s, int intf_reg, int vtable_reg, MonoClass *klass)
-{
- int ioffset_reg = mono_regstate_next_int (s->rs);
-
- MONO_EMIT_NEW_LOAD_MEMBASE (s, ioffset_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, interface_offsets));
- mini_emit_load_intf_reg (s, intf_reg, ioffset_reg, klass);
}
/* Emit code which loads <klass_reg>->interface_offsets [klass->interface_id] */
if (s->compile_aot) {
int iid_reg = mono_regstate_next_int (s->rs);
+ int shifted_iid_reg = mono_regstate_next_int (s->rs);
MONO_EMIT_NEW_AOTCONST (s, iid_reg, klass, MONO_PATCH_INFO_IID);
- MONO_EMIT_NEW_BIALU_IMM (s, OP_SHL_IMM, iid_reg, iid_reg, 2);
- MONO_EMIT_NEW_BIALU (s, CEE_ADD, ioffset_reg, ioffset_reg, iid_reg);
+ MONO_EMIT_NEW_BIALU_IMM (s, OP_SHL_IMM, shifted_iid_reg, iid_reg, 2);
+ MONO_EMIT_NEW_BIALU (s, CEE_ADD, ioffset_reg, ioffset_reg, shifted_iid_reg);
MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, intf_reg, ioffset_reg, 0);
- }
- else
+ } else {
MONO_EMIT_NEW_LOAD_MEMBASE_OP (s, OP_LOADI4_MEMBASE, intf_reg, ioffset_reg, klass->interface_id * sizeof (int));
+ }
}
void
MONO_EMIT_NEW_COND_EXC (s, EQ, "InvalidCastException");
}
-static int
-size_to_load_u_membase (int size)
-{
- switch (size) {
- case 1:
- return OP_LOADU1_MEMBASE;
- case 2:
- return OP_LOADU2_MEMBASE;
- case 4:
- return OP_LOADU4_MEMBASE;
- case 8:
- return OP_LOADI8_MEMBASE;
- default:
- g_assert_not_reached ();
- return -1;
- }
-}
-
-static int
-size_to_store_membase_reg (int size)
-{
- switch (size) {
- case 1:
- return OP_STOREI1_MEMBASE_REG;
- case 2:
- return OP_STOREI2_MEMBASE_REG;
- case 4:
- return OP_STOREI4_MEMBASE_REG;
- case 8:
- return OP_STOREI8_MEMBASE_REG;
- default:
- g_assert_not_reached ();
- return -1;
- }
-}
-
void
mini_emit_memcpy (MonoCompile *s, int destreg, int doffset, int srcreg, int soffset, int size, int align)
{
if (cfg->got_var->opcode == OP_REGOFFSET) {
got_var_reg = mono_regstate_next_int (cfg->rs);
MONO_EMIT_NEW_LOAD_MEMBASE (cfg, got_var_reg, cfg->got_var->inst_basereg, cfg->got_var->inst_offset);
- }
- else {
+ } else {
g_assert (cfg->got_var->opcode == OP_REGVAR);
got_var_reg = cfg->got_var->dreg;
}