From 387ba2d99b9eb92eedba4242e38e5ce8ff978af4 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Mon, 24 Jun 2024 13:04:10 -0700 Subject: [PATCH] Update mono to support Unsafe.BitCast --- src/mono/mono/mini/intrinsics.c | 119 ++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) diff --git a/src/mono/mono/mini/intrinsics.c b/src/mono/mono/mini/intrinsics.c index f4a92af12e386a..e49851daab69af 100644 --- a/src/mono/mono/mini/intrinsics.c +++ b/src/mono/mono/mini/intrinsics.c @@ -488,6 +488,125 @@ 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 (tto_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 (tto_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) { + // FIXME: `reginfo [sreg].born_in > 0' not met + // + // 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); + + return NULL; + } + + 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);