Skip to content

[Mono] [swift-interop] Add support for reverse pinvoke argument lowering #104437

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

Merged
merged 19 commits into from
Jul 15, 2024

Conversation

jkurdek
Copy link
Contributor

@jkurdek jkurdek commented Jul 4, 2024

Adds support in Mono for passing Swift @frozen struct as arguments to UnmanagedCallersOnly callbacks. Changes do not include support for lowering return value structs. That will come in separate PR. Detailed description of struct lowering can be found here #102143.


Changes introduce struct lowering on IL level to native-to-managed wrapper. First, the wrapper's signature is modified according to the result of struct lowering algorithm. For structs passed by reference we replace the struct arg with a reference arg. For a lowered struct, struct argument is replaced by a series of up to 4 primitive arguments.

Then, during wrapper's IL code generation, additional code is emitted to load the new arguments at correct offsets.


Verified full AOT locally.


Contributes to #102077

@jkurdek jkurdek added NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) NO-REVIEW Experimental/testing PR, do NOT review it labels Jul 4, 2024
@ghost ghost added the area-VM-meta-mono label Jul 4, 2024
@jkurdek
Copy link
Contributor Author

jkurdek commented Jul 8, 2024

/azp run runtime-extra-platforms

Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@jkurdek jkurdek changed the title Add support for reverse pinvoke argument lowering [Mono] [swift-interop] Add support for reverse pinvoke argument lowering Jul 8, 2024
@jkurdek jkurdek removed NO-MERGE The PR is not ready for merge yet (see discussion for detailed reasons) NO-REVIEW Experimental/testing PR, do NOT review it labels Jul 8, 2024
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

MonoClass *swift_self = mono_class_try_get_swift_self_class ();
MonoClass *swift_error = mono_class_try_get_swift_error_class ();
MonoClass *swift_indirect_result = mono_class_try_get_swift_indirect_result_class ();
swift_lowering = g_newa (SwiftPhysicalLowering, sig->param_count);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where are these deallocated?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Added deallocation for new_params. swift_lowering and swift_sig_to_csig_mp are allocated on stack, so we don't deallocate explicetely them right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Why they are allocated differently?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

swift_lowering and swift_sig_to_csig_mp are going to have exactly sig->param_count elements. In some places across marshalling code such arrays are allocated on stack.

tmp_locals = g_newa (int, sig->param_count);

swift_sig_to_csig_mp is an array of ints so I guess it ok. We could make the swift_lowering heap allocated, but I don't know whether this is necessary.

The new_params can be up to 4 times longer than theswift_lowering and swift_sig_to_csig_mp, as it includes the lowered params. So I following what was done in method-to-ir.

GArray *new_params = g_array_sized_new (FALSE, FALSE, sizeof (MonoType*), n);

}
}

csig = mono_metadata_signature_dup_new_params (NULL, NULL, get_method_image (method), csig, new_param_count, (MonoType**)new_params->data);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unsure where we should allocate the new csig. For the direct p/invokes we allocate the temporary signature in mempool but I suppose this is not temporary so image is probably the right choice.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea, I also think image is the right place.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm... actually... why not the mem manager of the method?

m_method_get_mem_manager (method). (That's usually the same as the image mempool, but for generic instances it will be the mempool of the whole set of images)

} else {
switch (t->type) {
case MONO_TYPE_VALUETYPE:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you need a MONO_TYPE_GENERICINST case to handle SwiftSelf<T> or other generics?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe currently we do not plan to support SwiftSelf<T> in reverse pinvokes #103576 (comment)

cc: @kotlarmilos

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -2575,13 +2576,13 @@ mono_metadata_signature_dup_delegate_invoke_to_target (MonoMethodSignature *sig)
* @return the new \c MonoMethodSignature structure.
*/
MonoMethodSignature*
mono_metadata_signature_dup_new_params (MonoMemPool *mp, MonoMemoryManager *mem_manager, MonoMethodSignature *sig, uint32_t num_params, MonoType **new_params)
mono_metadata_signature_dup_new_params (MonoMemPool *mp, MonoMemoryManager *mem_manager, MonoImage *image, MonoMethodSignature *sig, uint32_t num_params, MonoType **new_params)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should try to move away from passing MonoImage* to allocation functions. you can pass the mempool of the image if you need to. or better to get the mem manager for the method definition, I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reversed the change. Just for my education, why is passing MonoImage* a code smell?

Copy link
Member

@lambdageek lambdageek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mostly LGTM, but let's try to avoid adding a MonoImage* argument to the signature dup function. Using MonoImage* for allocation is a code smell.

Copy link
Member

@kotlarmilos kotlarmilos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@jkurdek jkurdek merged commit 9d24b13 into dotnet:main Jul 15, 2024
126 checks passed
@jkurdek jkurdek deleted the reverse-pinvokes-args-lowering branch July 15, 2024 13:40
@github-actions github-actions bot locked and limited conversation to collaborators Aug 15, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants