Skip to content

Commit

Permalink
Update mono to support Unsafe.BitCast
Browse files Browse the repository at this point in the history
  • Loading branch information
tannergooding committed Jun 25, 2024
1 parent 98e7570 commit 433e2bb
Showing 1 changed file with 115 additions and 0 deletions.
115 changes: 115 additions & 0 deletions src/mono/mono/mini/intrinsics.c
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,121 @@ emit_unsafe_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignatu
EMIT_NEW_BIALU (cfg, ins, OP_COMPARE, -1, args [0]->dreg, args [1]->dreg);
EMIT_NEW_UNALU (cfg, ins, OP_PCEQ, dreg, -1);
return ins;
} else if (!strcmp (cmethod->name, "BitCast")) {
g_assert (ctx);
g_assert (ctx->method_inst);
g_assert (ctx->method_inst->type_argc == 2);
g_assert (fsig->param_count == 1);

MonoType *tfrom = ctx->method_inst->type_argv [0];
if (mini_is_gsharedvt_variable_type (tfrom)) {
// FIXME: Handle gsharevt
return NULL;
}

MonoTypeEnum tfrom_type = tfrom->type;
MonoClass *tfrom_klass = mono_class_from_mono_type_internal (tfrom);
if (!m_class_is_valuetype (tfrom_klass)) {
return NULL;
}

MonoType *tto = ctx->method_inst->type_argv [1];
if (mini_is_gsharedvt_variable_type (tto)) {
// FIXME: Handle gsharevt
return NULL;
}

MonoTypeEnum tto_type = tto->type;
MonoClass *tto_klass = mono_class_from_mono_type_internal (tto);
if (!m_class_is_valuetype (tto_klass)) {
return NULL;
}

int tfrom_align, tto_align;
if (mono_type_size (tfrom, &tfrom_align) != mono_type_size (tto, &tto_align)) {
return NULL;
}

guint32 opcode = OP_LDADDR;
MonoStackType tfrom_stack = STACK_PTR;
MonoStackType tto_stack = STACK_OBJ;

if (tfrom_type == MONO_TYPE_I4) {
if (tto_type == MONO_TYPE_R4) {
opcode = OP_MOVE_I4_TO_F;
tfrom_stack = STACK_I4;
tto_stack = STACK_R4;
}
else if (tfrom_type == MONO_TYPE_I4) {
opcode = OP_MOVE;
tfrom_stack = STACK_I4;
tto_stack = STACK_I4;
}
}
else if (tfrom_type == MONO_TYPE_I8) {
if (tto_type == MONO_TYPE_R8) {
opcode = OP_MOVE_I8_TO_F;
tfrom_stack = STACK_I8;
tto_stack = STACK_R8;
}
else if (tfrom_type == MONO_TYPE_I8) {
opcode = OP_MOVE;
tfrom_stack = STACK_I8;
tto_stack = STACK_I8;
}
}
else if (tfrom_type == MONO_TYPE_R4) {
if (tto_type == MONO_TYPE_I4) {
opcode = OP_MOVE_F_TO_I4;
tfrom_stack = STACK_R4;
tto_stack = STACK_I4;
}
else if (tto_type == MONO_TYPE_R4) {
opcode = OP_RMOVE;
tfrom_stack = STACK_R4;
tto_stack = STACK_R4;
}
}
else if (tfrom_type == MONO_TYPE_R8) {
if (tto_type == MONO_TYPE_I8) {
opcode = OP_MOVE_F_TO_I8;
tfrom_stack = STACK_R8;
tto_stack = STACK_I8;
}
else if (tto_type == MONO_TYPE_R8) {
opcode = OP_FMOVE;
tfrom_stack = STACK_R8;
tto_stack = STACK_R8;
}
}
else if (mini_class_is_simd (cfg, tfrom_klass)) {
if (mini_class_is_simd (cfg, tto_klass)) {
// FIXME: Ensure that SIMD to SIMD conversions can be handled
//
// opcode = OP_XMOVE;
// tfrom_stack = STACK_VTYPE;
// tto_stack = STACK_VTYPE;
}
}

if (opcode == OP_LDADDR) {
MonoInst *arg0;
NEW_VARLOADA (cfg, arg0, args [0], tfrom);
arg0->dreg = mono_alloc_preg (cfg);

tto = mini_get_underlying_type (tto);
assert(MONO_TYPE_ISSTRUCT (tto));

if (cfg->gshared && (tto != ctx->method_inst->type_argv [1]) && mono_class_check_context_used (mono_class_from_mono_type_internal (tto)))
cfg->prefer_instances = TRUE;
return mini_emit_memory_load (cfg, tto, arg0, 0, MONO_INST_UNALIGNED);
}

int dreg = mono_alloc_dreg (cfg, tfrom_stack);
EMIT_NEW_UNALU (cfg, ins, opcode, dreg, args [0]->dreg);
ins->type = tto_stack;
ins->klass = tto_klass;
return ins;
} else if (!strcmp (cmethod->name, "IsAddressLessThan")) {
g_assert (ctx);
g_assert (ctx->method_inst);
Expand Down

0 comments on commit 433e2bb

Please sign in to comment.