diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index bff7eb1d3e3ad..96b8a5fe96de0 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -130,8 +130,9 @@ static GENERATE_TRY_GET_CLASS_WITH_CACHE (suppress_gc_transition_attribute, "Sys static GENERATE_TRY_GET_CLASS_WITH_CACHE (unmanaged_callers_only_attribute, "System.Runtime.InteropServices", "UnmanagedCallersOnlyAttribute") static GENERATE_TRY_GET_CLASS_WITH_CACHE (unmanaged_callconv_attribute, "System.Runtime.InteropServices", "UnmanagedCallConvAttribute") -GENERATE_TRY_GET_CLASS_WITH_CACHE (swift_error, "System.Runtime.InteropServices.Swift", "SwiftError") GENERATE_TRY_GET_CLASS_WITH_CACHE (swift_self, "System.Runtime.InteropServices.Swift", "SwiftSelf") +GENERATE_TRY_GET_CLASS_WITH_CACHE (swift_self_t, "System.Runtime.InteropServices.Swift", "SwiftSelf`1"); +GENERATE_TRY_GET_CLASS_WITH_CACHE (swift_error, "System.Runtime.InteropServices.Swift", "SwiftError") GENERATE_TRY_GET_CLASS_WITH_CACHE (swift_indirect_result, "System.Runtime.InteropServices.Swift", "SwiftIndirectResult") static gboolean type_is_blittable (MonoType *type); @@ -3698,12 +3699,14 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, if (mono_method_signature_has_ext_callconv (csig, MONO_EXT_CALLCONV_SWIFTCALL)) { MonoClass *swift_self = mono_class_try_get_swift_self_class (); + MonoClass *swift_self_t = mono_class_try_get_swift_self_t_class (); MonoClass *swift_error = mono_class_try_get_swift_error_class (); MonoClass *swift_indirect_result = mono_class_try_get_swift_indirect_result_class (); MonoClass *swift_error_ptr = mono_class_create_ptr (m_class_get_this_arg (swift_error)); int swift_error_args = 0, swift_self_args = 0, swift_indirect_result_args = 0; for (int i = 0; i < method->signature->param_count; ++i) { MonoClass *param_klass = mono_class_from_mono_type_internal (method->signature->params [i]); + MonoGenericClass *param_gklass = mono_class_try_get_generic_class (param_klass); if (param_klass) { if (param_klass == swift_error && !m_type_is_byref (method->signature->params [i])) { swift_error_args = swift_self_args = 0; @@ -3711,7 +3714,15 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, break; } else if (param_klass == swift_error || param_klass == swift_error_ptr) { swift_error_args++; - } else if (param_klass == swift_self) { + } else if (param_gklass && (param_gklass->container_class == swift_self_t) && i > 0) { + swift_error_args = swift_self_args = 0; + mono_error_set_generic_error (emitted_error, "System", "InvalidProgramException", "SwiftSelf must be the first argument in the signature."); + break; + } else if (param_gklass && (param_gklass->container_class == swift_self_t) && m_type_is_byref (method->signature->params [i])) { + swift_error_args = swift_self_args = 0; + mono_error_set_generic_error (emitted_error, "System", "InvalidProgramException", "Expected SwiftSelf struct, got pointer/reference."); + break; + } else if (param_klass == swift_self || (param_gklass && (param_gklass->container_class == swift_self_t))) { swift_self_args++; } else if (param_klass == swift_indirect_result) { swift_indirect_result_args++; diff --git a/src/mono/mono/metadata/marshal.h b/src/mono/mono/metadata/marshal.h index a682f4dc2b510..d36ad269c78c7 100644 --- a/src/mono/mono/metadata/marshal.h +++ b/src/mono/mono/metadata/marshal.h @@ -753,6 +753,7 @@ IlgenCallbacksToMono* mono_marshal_get_mono_callbacks_for_ilgen (void); GENERATE_TRY_GET_CLASS_WITH_CACHE_DECL (swift_self) +GENERATE_TRY_GET_CLASS_WITH_CACHE_DECL (swift_self_t); GENERATE_TRY_GET_CLASS_WITH_CACHE_DECL (swift_error) GENERATE_TRY_GET_CLASS_WITH_CACHE_DECL (swift_indirect_result) diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index 3a6a2d3944903..2b5e4c2c3fe61 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -3356,6 +3356,7 @@ interp_emit_swiftcall_struct_lowering (TransformData *td, MonoMethodSignature *c uint32_t new_param_count = 0; int align; MonoClass *swift_self = mono_class_try_get_swift_self_class (); + MonoClass *swift_self_t = mono_class_try_get_swift_self_t_class (); MonoClass *swift_error = mono_class_try_get_swift_error_class (); MonoClass *swift_indirect_result = mono_class_try_get_swift_indirect_result_class (); /* @@ -3366,6 +3367,8 @@ interp_emit_swiftcall_struct_lowering (TransformData *td, MonoMethodSignature *c for (int idx_param = 0; idx_param < csignature->param_count; ++idx_param) { MonoType *ptype = csignature->params [idx_param]; MonoClass *klass = mono_class_from_mono_type_internal (ptype); + MonoGenericClass *gklass = mono_class_try_get_generic_class (klass); + // SwiftSelf, SwiftError, and SwiftIndirectResult are special cases where we need to preserve the class information for the codegen to handle them correctly. if (mono_type_is_struct (ptype) && !(klass == swift_self || klass == swift_error || klass == swift_indirect_result)) { SwiftPhysicalLowering lowered_swift_struct = mono_marshal_get_swift_physical_lowering (ptype, FALSE); @@ -3386,8 +3389,13 @@ interp_emit_swiftcall_struct_lowering (TransformData *td, MonoMethodSignature *c g_array_append_val (new_params, lowered_swift_struct.lowered_elements [idx_lowered]); } } else { - // For structs that cannot be lowered, we change the argument to byref type - ptype = mono_class_get_byref_type (mono_defaults.typed_reference_class); + // For structs that cannot be lowered, we change the argument to a pointer-like argument type. + // If SwiftSelf can't be lowered, it should be passed in the same manner as SwiftSelf, via the context register. + if (gklass && (gklass->container_class == swift_self_t)) + ptype = mono_class_get_byref_type (swift_self); + else + ptype = mono_class_get_byref_type (klass); + // Load the address of the struct interp_add_ins (td, MINT_LDLOCA_S); interp_ins_set_sreg (td->last_ins, sp_old_params [idx_param].var); diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index d3b0637119d07..6734b2d0ce5c3 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -7533,6 +7533,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b GArray *new_params = g_array_sized_new (FALSE, FALSE, sizeof (MonoType*), n); uint32_t new_param_count = 0; MonoClass *swift_self = mono_class_try_get_swift_self_class (); + MonoClass *swift_self_t = mono_class_try_get_swift_self_t_class (); MonoClass *swift_error = mono_class_try_get_swift_error_class (); MonoClass *swift_indirect_result = mono_class_try_get_swift_indirect_result_class (); /* @@ -7543,6 +7544,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b for (int idx_param = 0; idx_param < n; ++idx_param) { MonoType *ptype = fsig->params [idx_param]; MonoClass *klass = mono_class_from_mono_type_internal (ptype); + MonoGenericClass *gklass = mono_class_try_get_generic_class (klass); // SwiftSelf, SwiftError, and SwiftIndirectResult are special cases where we need to preserve the class information for the codegen to handle them correctly. if (mono_type_is_struct (ptype) && !(klass == swift_self || klass == swift_error || klass == swift_indirect_result)) { @@ -7562,9 +7564,17 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b ++new_param_count; } } else { - // For structs that cannot be lowered, we change the argument to byref type + // For structs that cannot be lowered, we change the argument to a pointer-like argument type. + // If SwiftSelf can't be lowered, it should be passed in the same manner as SwiftSelf, via the context register. + if (gklass && (gklass->container_class == swift_self_t)) { + ptype = mono_class_get_byref_type (swift_self); + // The ARGLOADA should be a pointer-like type. + struct_base_address->klass = mono_defaults.int_class; + } else { + ptype = mono_class_get_byref_type (klass); + } + *sp++ = struct_base_address; - ptype = mono_class_get_byref_type (klass); g_array_append_val (new_params, ptype); ++new_param_count; diff --git a/src/mono/mono/mini/mini-amd64.c b/src/mono/mono/mini/mini-amd64.c index ed40ecadae0a6..096fcea3e01d9 100644 --- a/src/mono/mono/mini/mini-amd64.c +++ b/src/mono/mono/mini/mini-amd64.c @@ -1096,8 +1096,7 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) if ((klass == swift_self || klass == swift_indirect_result) && sig->pinvoke) { guint32 size = mini_type_stack_size_full (m_class_get_byval_arg (klass), NULL, sig->pinvoke && !sig->marshalling_disabled); - g_assert (size == 8); - + g_assert (size == TARGET_SIZEOF_VOID_P); ainfo->storage = ArgValuetypeInReg; ainfo->pair_storage [0] = ArgInIReg; ainfo->pair_storage [1] = ArgNone; diff --git a/src/mono/mono/mini/mini-arm64.c b/src/mono/mono/mini/mini-arm64.c index 903a8bc9965f7..d7f5c395829f5 100644 --- a/src/mono/mono/mini/mini-arm64.c +++ b/src/mono/mono/mini/mini-arm64.c @@ -1922,8 +1922,7 @@ get_call_info (MonoMemPool *mp, MonoMethodSignature *sig) guint32 align; MonoType *ptype = mini_get_underlying_type (sig->params [pindex]); int size = mini_type_stack_size_full (ptype, &align, cinfo->pinvoke); - g_assert (size == 8); - + g_assert (size == TARGET_SIZEOF_VOID_P); ainfo->storage = ArgVtypeInIRegs; ainfo->reg = (klass == swift_self) ? ARMREG_R20 : ARMREG_R8; ainfo->nregs = 1; diff --git a/src/tests/Interop/Swift/SwiftSelfContext/SwiftSelfContext.cs b/src/tests/Interop/Swift/SwiftSelfContext/SwiftSelfContext.cs index 77c046cf82480..8899985b99ac1 100644 --- a/src/tests/Interop/Swift/SwiftSelfContext/SwiftSelfContext.cs +++ b/src/tests/Interop/Swift/SwiftSelfContext/SwiftSelfContext.cs @@ -69,7 +69,6 @@ public struct FrozenNonEnregisteredStruct public static extern long SumFrozenNonEnregisteredStruct(SwiftSelf self); [Fact] - [SkipOnMono("SwiftSelf is not supported on Mono")] public unsafe static void TestSelfIsFrozenEnregisteredStruct() { long sum = SumFrozenEnregisteredStruct(new SwiftSelf(new FrozenEnregisteredStruct { A = 10, B = 20 })); @@ -77,7 +76,6 @@ public unsafe static void TestSelfIsFrozenEnregisteredStruct() } [Fact] - [SkipOnMono("SwiftSelf is not supported on Mono")] public unsafe static void TestSelfIsFrozenNonEnregisteredStruct() { long sum = SumFrozenNonEnregisteredStruct(new SwiftSelf(new FrozenNonEnregisteredStruct { A = 10, B = 20, C = 30, D = 40, E = 50 }));