- MonoClass *base_class = mono_class_from_mono_type (target);
- /* This is needed to handle gshared types + ldaddr */
- simple_type = mini_get_underlying_type (&base_class->byval_arg);
- return target->type != MONO_TYPE_I && arg->klass != base_class && arg->klass != mono_class_from_mono_type (simple_type);
+ if (cfg->verbose_level) printf ("ok\n");
+ /* This is needed to handle gshared types + ldaddr. We lower the types so we can handle enums and other typedef-like types. */
+ MonoClass *target_class_lowered = mono_class_from_mono_type (mini_get_underlying_type (&mono_class_from_mono_type (target)->byval_arg));
+ MonoClass *source_class_lowered = mono_class_from_mono_type (mini_get_underlying_type (&arg->klass->byval_arg));
+
+ /* if the target is native int& or same type */
+ if (target->type == MONO_TYPE_I || target_class_lowered == source_class_lowered)
+ return 0;
+
+ /* Both are primitive type byrefs and the source points to a larger type that the destination */
+ if (MONO_TYPE_IS_PRIMITIVE_SCALAR (&target_class_lowered->byval_arg) && MONO_TYPE_IS_PRIMITIVE_SCALAR (&source_class_lowered->byval_arg) &&
+ mono_class_instance_size (target_class_lowered) <= mono_class_instance_size (source_class_lowered))
+ return 0;
+ return 1;