Skip to content
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

[Mono] added simple reverse pinvoke support to interpreter #102185

Merged
merged 12 commits into from
May 17, 2024
1 change: 1 addition & 0 deletions src/mono/mono/mini/interp/interp-internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ struct InterpMethod {
MonoProfilerCallInstrumentationFlags prof_flags;
InterpMethodCodeType code_type;
int ref_slot_offset; // GC visible pointer slot
int swift_error_offset; // swift error struct
MonoBitSet *ref_slots;
#ifdef ENABLE_EXPERIMENT_TIERED
MiniTieredCounter tiered_counter;
Expand Down
27 changes: 26 additions & 1 deletion src/mono/mono/mini/interp/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -3176,6 +3176,20 @@ interp_entry_from_trampoline (gpointer ccontext_untyped, gpointer rmethod_untype
/* Copy the args saved in the trampoline to the frame stack */
gpointer retp = mono_arch_get_native_call_context_args (ccontext, &frame, sig, call_info);

#ifdef MONO_ARCH_HAVE_SWIFTCALL
int swift_error_arg_index = -1;
gpointer swift_error_data;
gpointer* swift_error_pointer;
if (mono_method_signature_has_ext_callconv (sig, MONO_EXT_CALLCONV_SWIFTCALL)) {
swift_error_data = mono_arch_get_swift_error (ccontext, sig, &swift_error_arg_index);

int swift_error_offset = frame.imethod->swift_error_offset;
if (swift_error_offset >= 0) {
swift_error_pointer = (gpointer*)((guchar*)frame.stack + swift_error_offset);
}
}
#endif

/* Allocate storage for value types */
stackval *newsp = sp;
/* FIXME we should reuse computation on imethod for this */
Expand All @@ -3195,6 +3209,11 @@ interp_entry_from_trampoline (gpointer ccontext_untyped, gpointer rmethod_untype
} else {
size = MINT_STACK_SLOT_SIZE;
}
#ifdef MONO_ARCH_HAVE_SWIFTCALL
if (swift_error_arg_index >= 0 && swift_error_arg_index == i) {
newsp->data.p = swift_error_pointer;
jkurdek marked this conversation as resolved.
Show resolved Hide resolved
}
#endif
newsp = STACK_ADD_BYTES (newsp, size);
}
newsp = (stackval*)ALIGN_TO (newsp, MINT_STACK_ALIGNMENT);
Expand All @@ -3205,6 +3224,12 @@ interp_entry_from_trampoline (gpointer ccontext_untyped, gpointer rmethod_untype
mono_interp_exec_method (&frame, context, NULL);
MONO_EXIT_GC_UNSAFE;

#ifdef MONO_ARCH_HAVE_SWIFTCALL
if (swift_error_arg_index >= 0) {
*(gpointer*)swift_error_data = *(gpointer*)swift_error_pointer;
}
#endif

context->stack_pointer = (guchar*)sp;
g_assert (!context->has_resume_state);

Expand Down Expand Up @@ -3459,7 +3484,7 @@ interp_create_method_pointer (MonoMethod *method, gboolean compile, MonoError *e
return (gpointer)no_llvmonly_interp_method_pointer;
}

#ifndef MONO_ARCH_HAVE_FTNPTR_ARG_TRAMPOLINE
#if !defined(MONO_ARCH_HAVE_FTNPTR_ARG_TRAMPOLINE) && !defined(MONO_ARCH_HAVE_SWIFTCALL)
jkurdek marked this conversation as resolved.
Show resolved Hide resolved
/*
* Interp in wrappers get the argument in the rgctx register. If
* MONO_ARCH_HAVE_FTNPTR_ARG_TRAMPOLINE is defined it means that
Expand Down
37 changes: 37 additions & 0 deletions src/mono/mono/mini/interp/transform.c
Original file line number Diff line number Diff line change
Expand Up @@ -4417,6 +4417,43 @@ interp_method_compute_offsets (TransformData *td, InterpMethod *imethod, MonoMet
td->il_locals_size = offset - td->il_locals_offset;
td->total_locals_size = offset;

#ifdef MONO_ARCH_HAVE_SWIFTCALL
// Allocate SwiftError
if (mono_method_signature_has_ext_callconv (sig, MONO_EXT_CALLCONV_SWIFTCALL)) {
imethod->swift_error_offset = -1;

MonoClass *swift_error = mono_class_try_get_swift_error_class ();
MonoClass *swift_error_ptr = mono_class_create_ptr (m_class_get_this_arg (swift_error));

int swift_error_index = -1;
for (int i = 0; i < sig->param_count; i++) {
jkurdek marked this conversation as resolved.
Show resolved Hide resolved
MonoClass *klass = mono_class_from_mono_type_internal (sig->params [i]);
if (klass == swift_error_ptr) {
swift_error_index = i;
break;
}
}
Copy link
Member Author

Choose a reason for hiding this comment

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

We could probably hardcode type and allocate this variable without checking whether SwiftError* exists on signature

Copy link
Member

@kotlarmilos kotlarmilos May 16, 2024

Choose a reason for hiding this comment

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

Sounds good. It can allocate a variable for SwiftError* if a signature is CallConvSwift.

Copy link
Member Author

Choose a reason for hiding this comment

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

I got rid of the loop as you suggested. I don't think there is a significant benefit of hardcoding it now. What you think?


if (swift_error_index >= 0)
{
MonoType* type = mono_method_signature_internal (td->method)->params [swift_error_index - sig->hasthis];
int index = num_args + num_il_locals;
int mt = mono_mint_type (type);

td->vars [index].type = type;
td->vars [index].global = TRUE;
td->vars [index].offset = offset;
size = mono_interp_type_size (type, mt, &align);
td->vars [index].size = size;
interp_mark_ref_slots_for_var (td, index);

offset += size;
offset = ALIGN_TO (offset, MINT_STACK_ALIGNMENT);
imethod->swift_error_offset = td->vars [index].offset;
jkurdek marked this conversation as resolved.
Show resolved Hide resolved
}
}
#endif

imethod->clause_data_offsets = (guint32*)g_malloc (header->num_clauses * sizeof (guint32));
td->clause_vars = (int*)mono_mempool_alloc (td->mempool, sizeof (int) * header->num_clauses);
for (guint i = 0; i < header->num_clauses; i++) {
Expand Down
14 changes: 14 additions & 0 deletions src/mono/mono/mini/mini-arm64.c
Original file line number Diff line number Diff line change
Expand Up @@ -2081,10 +2081,24 @@ mono_arch_set_native_call_context_ret (CallContext *ccontext, gpointer frame, Mo
storage = alloca (temp_size);
else
storage = arg_get_storage (ccontext, ainfo);

#ifdef MONO_ARCH_HAVE_SWIFTCALL
int swift_error_preserved_val = 0;
if (ccontext->gregs [PARAM_REGS + 2]) {
swift_error_preserved_val = ccontext->gregs [PARAM_REGS + 2];
}
#endif

memset (ccontext, 0, sizeof (CallContext)); // FIXME
jkurdek marked this conversation as resolved.
Show resolved Hide resolved
interp_cb->frame_arg_to_data ((MonoInterpFrameHandle)frame, sig, -1, storage);
if (temp_size)
arg_set_val (ccontext, ainfo, storage);

#ifdef MONO_ARCH_HAVE_SWIFTCALL
if (swift_error_preserved_val > 0) {
ccontext->gregs [PARAM_REGS + 2] = swift_error_preserved_val;
}
#endif
}
}

Expand Down
13 changes: 13 additions & 0 deletions src/mono/mono/mini/tramp-arm64.c
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,13 @@ mono_arch_get_native_to_interp_trampoline (MonoTrampInfo **info)
for (i = 0; i < FP_PARAM_REGS; i++)
arm_strfpx (code, i, ARMREG_FP, ccontext_offset + MONO_STRUCT_OFFSET (CallContext, fregs) + i * sizeof (double));

#ifdef MONO_ARCH_HAVE_SWIFTCALL
/* set context registers to CallContext */
for (i = 0; i < CTX_REGS; i++) {
arm_strx (code, i + CTX_REGS_OFFSET, ARMREG_FP, ccontext_offset + MONO_STRUCT_OFFSET (CallContext, gregs) + (i + PARAM_REGS + 1) * sizeof (host_mgreg_t));
}
#endif

/* set the stack pointer to the value at call site */
arm_addx_imm (code, ARMREG_R0, ARMREG_FP, framesize);
arm_strp (code, ARMREG_R0, ARMREG_FP, ccontext_offset + MONO_STRUCT_OFFSET (CallContext, stack));
Expand All @@ -863,6 +870,12 @@ mono_arch_get_native_to_interp_trampoline (MonoTrampInfo **info)
for (i = 0; i < FP_PARAM_REGS; i++)
arm_ldrfpx (code, i, ARMREG_FP, ccontext_offset + MONO_STRUCT_OFFSET (CallContext, fregs) + i * sizeof (double));

#ifdef MONO_ARCH_HAVE_SWIFTCALL
/* set the context registers from CallContext */
for (i = 0; i < CTX_REGS; i++) {
arm_ldrx (code, i + CTX_REGS_OFFSET, ARMREG_FP, ccontext_offset + MONO_STRUCT_OFFSET (CallContext, gregs) + (i + PARAM_REGS + 1) * sizeof (host_mgreg_t));
}
#endif
/* reset stack and return */
arm_ldpx (code, ARMREG_FP, ARMREG_LR, ARMREG_SP, 0);
arm_addx_imm (code, ARMREG_SP, ARMREG_SP, framesize);
Expand Down
3 changes: 0 additions & 3 deletions src/tests/issues.targets
Original file line number Diff line number Diff line change
Expand Up @@ -2145,9 +2145,6 @@
<ExcludeList Include = "$(XUnitTestBinBase)/JIT/Directed/Arrays/nintindexoutofrange/**">
<Issue>https://github.com/dotnet/runtime/issues/71656</Issue>
</ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/Interop/Swift/SwiftErrorHandling/**">
<Issue>Reverse P/Invokes not supported yet</Issue>
</ExcludeList>
<!-- End interpreter issues -->
</ItemGroup>

Expand Down
Loading