-
Notifications
You must be signed in to change notification settings - Fork 5.2k
[mono][swift-interop] Support for Swift frozen struct lowering in mini-JIT/AOT/interpreter #102143
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d664b69
b305cb3
2764076
5294446
91a5e7a
49d5afb
b564238
96a6fd3
ba829c8
241765b
0638729
2376d05
f0e8da4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3320,6 +3320,95 @@ interp_try_devirt (MonoClass *this_klass, MonoMethod *target_method) | |
| return NULL; | ||
| } | ||
|
|
||
| static MonoMethodSignature* | ||
| interp_emit_swiftcall_struct_lowering (TransformData *td, MonoMethodSignature *csignature) | ||
| { | ||
| // P/Invoke calls shouldn't contain 'this' | ||
| g_assert (!csignature->hasthis); | ||
|
|
||
| /* | ||
| * Argument reordering here doesn't handle on the fly offset allocation | ||
| * and requires the full var offset allocator pass that is only ran for optimized code | ||
| */ | ||
| g_assert (td->optimized); | ||
|
|
||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The argument moving around that happens here will break the fast offset allocator (where we allocate storage for vars immediately as we push it on the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, we only need to perform the struct lowering for m2n (and later eventually n2m) wrappers. I added the assert with the comment you suggested. |
||
| MonoMethodSignature *new_csignature; | ||
| // Save the function pointer | ||
| StackInfo sp_fp = td->sp [-1]; | ||
| --td->sp; | ||
|
|
||
| // Save the old arguments | ||
| td->sp -= csignature->param_count; | ||
| StackInfo *sp_old_params = (StackInfo*) mono_mempool_alloc (td->mempool, sizeof (StackInfo) * csignature->param_count); | ||
| for (int i = 0; i < csignature->param_count; ++i) | ||
| sp_old_params [i] = td->sp [i]; | ||
|
|
||
| GArray *new_params = g_array_sized_new (FALSE, FALSE, sizeof (MonoType*), csignature->param_count); | ||
| uint32_t new_param_count = 0; | ||
| int align; | ||
| MonoClass *swift_self = mono_class_try_get_swift_self_class (); | ||
| MonoClass *swift_error = mono_class_try_get_swift_error_class (); | ||
| /* | ||
| * Go through the lowered arguments, if the argument is a struct, | ||
| * we need to replace it with a sequence of lowered arguments. | ||
| * Also record the updated parameters for the new signature. | ||
| */ | ||
| 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); | ||
| // SwiftSelf and SwiftError 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)) { | ||
| SwiftPhysicalLowering lowered_swift_struct = mono_marshal_get_swift_physical_lowering (ptype, FALSE); | ||
| if (!lowered_swift_struct.by_reference) { | ||
| for (uint32_t idx_lowered = 0; idx_lowered < lowered_swift_struct.num_lowered_elements; ++idx_lowered) { | ||
| int mt_lowered = mono_mint_type (lowered_swift_struct.lowered_elements [idx_lowered]); | ||
| int lowered_elem_size = mono_type_size (lowered_swift_struct.lowered_elements [idx_lowered], &align); | ||
| // Load the lowered elements of the struct | ||
| interp_add_ins (td, MINT_MOV_SRC_OFF); | ||
| interp_ins_set_sreg (td->last_ins, sp_old_params [idx_param].var); | ||
| td->last_ins->data [0] = (guint16) lowered_swift_struct.offsets [idx_lowered]; | ||
| td->last_ins->data [1] = GINT_TO_UINT16 (mt_lowered); | ||
| td->last_ins->data [2] = GINT_TO_UINT16 (lowered_elem_size); | ||
| push_mono_type (td, lowered_swift_struct.lowered_elements [idx_lowered], mt_lowered, mono_class_from_mono_type_internal (lowered_swift_struct.lowered_elements [idx_lowered])); | ||
| interp_ins_set_dreg (td->last_ins, td->sp [-1].var); | ||
|
|
||
| ++new_param_count; | ||
| 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); | ||
| // 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); | ||
| push_simple_type (td, STACK_TYPE_I); | ||
| interp_ins_set_dreg (td->last_ins, td->sp [-1].var); | ||
|
|
||
| ++new_param_count; | ||
| g_array_append_val (new_params, ptype); | ||
| } | ||
| } else { | ||
| // Copy over non-struct arguments | ||
| memcpy (td->sp, &sp_old_params [idx_param], sizeof (StackInfo)); | ||
| ++td->sp; | ||
|
|
||
| ++new_param_count; | ||
| g_array_append_val (new_params, ptype); | ||
| } | ||
| } | ||
| // Restore the function pointer | ||
| memcpy (td->sp, &sp_fp, sizeof (StackInfo)); | ||
| ++td->sp; | ||
|
|
||
| // Create a new dummy signature with the lowered arguments | ||
| new_csignature = mono_metadata_signature_dup_new_params (td->mempool, csignature, new_param_count, (MonoType**)new_params->data); | ||
|
|
||
| // Deallocate temp array | ||
| g_array_free (new_params, TRUE); | ||
|
|
||
| return new_csignature; | ||
| } | ||
|
|
||
| /* Return FALSE if error, including inline failure */ | ||
| static gboolean | ||
| interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target_method, MonoGenericContext *generic_context, MonoClass *constrained_class, gboolean readonly, MonoError *error, gboolean check_visibility, gboolean save_last_error, gboolean tailcall) | ||
|
|
@@ -3404,6 +3493,16 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target | |
| return FALSE; | ||
| } | ||
|
|
||
| #ifdef MONO_ARCH_HAVE_SWIFTCALL | ||
| /* | ||
| * We need to modify the signature of the swiftcall calli to account for the lowering of Swift structs. | ||
| * This is done by replacing struct arguments on stack with a lowered sequence and updating the signature. | ||
| */ | ||
| if (csignature->pinvoke && mono_method_signature_has_ext_callconv (csignature, MONO_EXT_CALLCONV_SWIFTCALL)) { | ||
| csignature = interp_emit_swiftcall_struct_lowering (td, csignature); | ||
| } | ||
| #endif | ||
|
|
||
| if (check_visibility && target_method && !mono_method_can_access_method (method, target_method)) | ||
| interp_generate_mae_throw (td, method, target_method); | ||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.