Skip to content

Commit 433e2bb

Browse files
committed
Update mono to support Unsafe.BitCast
1 parent 98e7570 commit 433e2bb

File tree

1 file changed

+115
-0
lines changed

1 file changed

+115
-0
lines changed

src/mono/mono/mini/intrinsics.c

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,121 @@ emit_unsafe_intrinsics (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignatu
488488
EMIT_NEW_BIALU (cfg, ins, OP_COMPARE, -1, args [0]->dreg, args [1]->dreg);
489489
EMIT_NEW_UNALU (cfg, ins, OP_PCEQ, dreg, -1);
490490
return ins;
491+
} else if (!strcmp (cmethod->name, "BitCast")) {
492+
g_assert (ctx);
493+
g_assert (ctx->method_inst);
494+
g_assert (ctx->method_inst->type_argc == 2);
495+
g_assert (fsig->param_count == 1);
496+
497+
MonoType *tfrom = ctx->method_inst->type_argv [0];
498+
if (mini_is_gsharedvt_variable_type (tfrom)) {
499+
// FIXME: Handle gsharevt
500+
return NULL;
501+
}
502+
503+
MonoTypeEnum tfrom_type = tfrom->type;
504+
MonoClass *tfrom_klass = mono_class_from_mono_type_internal (tfrom);
505+
if (!m_class_is_valuetype (tfrom_klass)) {
506+
return NULL;
507+
}
508+
509+
MonoType *tto = ctx->method_inst->type_argv [1];
510+
if (mini_is_gsharedvt_variable_type (tto)) {
511+
// FIXME: Handle gsharevt
512+
return NULL;
513+
}
514+
515+
MonoTypeEnum tto_type = tto->type;
516+
MonoClass *tto_klass = mono_class_from_mono_type_internal (tto);
517+
if (!m_class_is_valuetype (tto_klass)) {
518+
return NULL;
519+
}
520+
521+
int tfrom_align, tto_align;
522+
if (mono_type_size (tfrom, &tfrom_align) != mono_type_size (tto, &tto_align)) {
523+
return NULL;
524+
}
525+
526+
guint32 opcode = OP_LDADDR;
527+
MonoStackType tfrom_stack = STACK_PTR;
528+
MonoStackType tto_stack = STACK_OBJ;
529+
530+
if (tfrom_type == MONO_TYPE_I4) {
531+
if (tto_type == MONO_TYPE_R4) {
532+
opcode = OP_MOVE_I4_TO_F;
533+
tfrom_stack = STACK_I4;
534+
tto_stack = STACK_R4;
535+
}
536+
else if (tfrom_type == MONO_TYPE_I4) {
537+
opcode = OP_MOVE;
538+
tfrom_stack = STACK_I4;
539+
tto_stack = STACK_I4;
540+
}
541+
}
542+
else if (tfrom_type == MONO_TYPE_I8) {
543+
if (tto_type == MONO_TYPE_R8) {
544+
opcode = OP_MOVE_I8_TO_F;
545+
tfrom_stack = STACK_I8;
546+
tto_stack = STACK_R8;
547+
}
548+
else if (tfrom_type == MONO_TYPE_I8) {
549+
opcode = OP_MOVE;
550+
tfrom_stack = STACK_I8;
551+
tto_stack = STACK_I8;
552+
}
553+
}
554+
else if (tfrom_type == MONO_TYPE_R4) {
555+
if (tto_type == MONO_TYPE_I4) {
556+
opcode = OP_MOVE_F_TO_I4;
557+
tfrom_stack = STACK_R4;
558+
tto_stack = STACK_I4;
559+
}
560+
else if (tto_type == MONO_TYPE_R4) {
561+
opcode = OP_RMOVE;
562+
tfrom_stack = STACK_R4;
563+
tto_stack = STACK_R4;
564+
}
565+
}
566+
else if (tfrom_type == MONO_TYPE_R8) {
567+
if (tto_type == MONO_TYPE_I8) {
568+
opcode = OP_MOVE_F_TO_I8;
569+
tfrom_stack = STACK_R8;
570+
tto_stack = STACK_I8;
571+
}
572+
else if (tto_type == MONO_TYPE_R8) {
573+
opcode = OP_FMOVE;
574+
tfrom_stack = STACK_R8;
575+
tto_stack = STACK_R8;
576+
}
577+
}
578+
else if (mini_class_is_simd (cfg, tfrom_klass)) {
579+
if (mini_class_is_simd (cfg, tto_klass)) {
580+
// FIXME: Ensure that SIMD to SIMD conversions can be handled
581+
//
582+
// opcode = OP_XMOVE;
583+
// tfrom_stack = STACK_VTYPE;
584+
// tto_stack = STACK_VTYPE;
585+
}
586+
}
587+
588+
if (opcode == OP_LDADDR) {
589+
MonoInst *arg0;
590+
NEW_VARLOADA (cfg, arg0, args [0], tfrom);
591+
arg0->dreg = mono_alloc_preg (cfg);
592+
593+
tto = mini_get_underlying_type (tto);
594+
assert(MONO_TYPE_ISSTRUCT (tto));
595+
596+
if (cfg->gshared && (tto != ctx->method_inst->type_argv [1]) && mono_class_check_context_used (mono_class_from_mono_type_internal (tto)))
597+
cfg->prefer_instances = TRUE;
598+
return mini_emit_memory_load (cfg, tto, arg0, 0, MONO_INST_UNALIGNED);
599+
}
600+
601+
int dreg = mono_alloc_dreg (cfg, tfrom_stack);
602+
EMIT_NEW_UNALU (cfg, ins, opcode, dreg, args [0]->dreg);
603+
ins->type = tto_stack;
604+
ins->klass = tto_klass;
605+
return ins;
491606
} else if (!strcmp (cmethod->name, "IsAddressLessThan")) {
492607
g_assert (ctx);
493608
g_assert (ctx->method_inst);

0 commit comments

Comments
 (0)