Skip to content

Commit 9d24b13

Browse files
jkurdeklambdageek
andauthored
[Mono] [swift-interop] Add support for reverse pinvoke argument lowering (#104437)
* Add support for reverse pinvoke argument lowering * Fix ILGeneration tests errors * Fix build errors * Reworked structure reassemble algorithm to work on sig * Fix x64 test errors * Add support for SwiftIndirectResult * Remove duplicate call to lowering algorithm * Refactor emitting swift lowered struct * Fix formatting * Remove extra newline * Fix SwiftIndirectResult errors * Address review comments * Fix loop indent * Update src/mono/mono/metadata/marshal-lightweight.c Co-authored-by: Aleksey Kliger (λgeek) <akliger@gmail.com> * Remove passing MonoImage * Fix formatting around conditional blocks * Fix missing whitespace --------- Co-authored-by: Aleksey Kliger (λgeek) <akliger@gmail.com>
1 parent a20847d commit 9d24b13

File tree

5 files changed

+176
-28
lines changed

5 files changed

+176
-28
lines changed

src/mono/mono/metadata/marshal-lightweight.c

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2715,13 +2715,47 @@ emit_managed_wrapper_validate_signature (MonoMethodSignature* sig, MonoMarshalSp
27152715
return TRUE;
27162716
}
27172717

2718+
static void
2719+
emit_swift_lowered_struct_load (MonoMethodBuilder *mb, MonoMethodSignature *csig, SwiftPhysicalLowering swift_lowering, int tmp_local, uint32_t csig_argnum)
2720+
{
2721+
guint8 stind_op;
2722+
uint32_t offset = 0;
2723+
2724+
for (uint32_t idx_lowered = 0; idx_lowered < swift_lowering.num_lowered_elements; idx_lowered++) {
2725+
offset = swift_lowering.offsets [idx_lowered];
2726+
mono_mb_emit_ldloc_addr (mb, tmp_local);
2727+
mono_mb_emit_icon (mb, offset);
2728+
mono_mb_emit_byte (mb, CEE_ADD);
2729+
2730+
mono_mb_emit_ldarg (mb, csig_argnum + idx_lowered);
2731+
stind_op = mono_type_to_stind (csig->params [csig_argnum + idx_lowered]);
2732+
mono_mb_emit_byte (mb, stind_op);
2733+
}
2734+
}
2735+
2736+
/* Swift struct lowering handling causes csig to have additional arguments.
2737+
* This function returns the index of the argument in the csig that corresponds to the argument in the original signature.
2738+
*/
2739+
static int
2740+
get_csig_argnum (int i, EmitMarshalContext* m)
2741+
{
2742+
if (m->swift_sig_to_csig_mp) {
2743+
g_assert (i < m->sig->param_count);
2744+
int csig_argnum = m->swift_sig_to_csig_mp [i];
2745+
g_assert (csig_argnum >= 0 && csig_argnum < m->csig->param_count);
2746+
return csig_argnum;
2747+
}
2748+
return i;
2749+
}
2750+
27182751
static void
27192752
emit_managed_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, MonoGCHandle target_handle, gboolean runtime_init_callback, MonoError *error)
27202753
{
27212754
MonoMethodSignature *sig, *csig;
27222755
int i, *tmp_locals;
27232756
gboolean closed = FALSE;
27242757
GCUnsafeTransitionBuilder gc_unsafe_builder = {0,};
2758+
SwiftPhysicalLowering *swift_lowering = m->swift_lowering;
27252759

27262760
sig = m->sig;
27272761
csig = m->csig;
@@ -2798,19 +2832,31 @@ emit_managed_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *invoke_s
27982832
for (i = 0; i < sig->param_count; i ++) {
27992833
MonoType *t = sig->params [i];
28002834
MonoMarshalSpec *spec = mspecs [i + 1];
2835+
int csig_argnum = get_csig_argnum (i, m);
28012836

28022837
if (spec && spec->native == MONO_NATIVE_CUSTOM) {
2803-
tmp_locals [i] = mono_emit_marshal (m, i, t, mspecs [i + 1], 0, &csig->params [i], MARSHAL_ACTION_MANAGED_CONV_IN);
2838+
tmp_locals [i] = mono_emit_marshal (m, csig_argnum, t, mspecs [i + 1], 0, &csig->params [csig_argnum], MARSHAL_ACTION_MANAGED_CONV_IN);
28042839
} else {
28052840
switch (t->type) {
2841+
case MONO_TYPE_VALUETYPE:
2842+
if (mono_method_signature_has_ext_callconv (csig, MONO_EXT_CALLCONV_SWIFTCALL)) {
2843+
if (swift_lowering [i].num_lowered_elements > 0) {
2844+
tmp_locals [i] = mono_mb_add_local (mb, sig->params [i]);
2845+
emit_swift_lowered_struct_load (mb, csig, swift_lowering [i], tmp_locals [i], csig_argnum);
2846+
break;
2847+
} else if (swift_lowering [i].by_reference) {
2848+
/* Structs passed by reference are handled during arg loading emission */
2849+
tmp_locals [i] = 0;
2850+
break;
2851+
}
2852+
} /* else fallthru */
28062853
case MONO_TYPE_OBJECT:
28072854
case MONO_TYPE_CLASS:
2808-
case MONO_TYPE_VALUETYPE:
28092855
case MONO_TYPE_ARRAY:
28102856
case MONO_TYPE_SZARRAY:
28112857
case MONO_TYPE_STRING:
28122858
case MONO_TYPE_BOOLEAN:
2813-
tmp_locals [i] = mono_emit_marshal (m, i, t, mspecs [i + 1], 0, &csig->params [i], MARSHAL_ACTION_MANAGED_CONV_IN);
2859+
tmp_locals [i] = mono_emit_marshal (m, csig_argnum, t, mspecs [i + 1], 0, &csig->params [csig_argnum], MARSHAL_ACTION_MANAGED_CONV_IN);
28142860
break;
28152861
default:
28162862
tmp_locals [i] = 0;
@@ -2836,15 +2882,18 @@ emit_managed_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *invoke_s
28362882

28372883
for (i = 0; i < sig->param_count; i++) {
28382884
MonoType *t = sig->params [i];
2839-
2840-
if (tmp_locals [i]) {
2885+
int csig_argnum = get_csig_argnum (i, m);
2886+
if (mono_method_signature_has_ext_callconv (csig, MONO_EXT_CALLCONV_SWIFTCALL) && swift_lowering [i].by_reference) {
2887+
mono_mb_emit_ldarg (mb, csig_argnum);
2888+
MonoClass* klass = mono_class_from_mono_type_internal (sig->params [i]);
2889+
mono_mb_emit_op (mb, CEE_LDOBJ, klass);
2890+
} else if (tmp_locals [i]) {
28412891
if (m_type_is_byref (t))
28422892
mono_mb_emit_ldloc_addr (mb, tmp_locals [i]);
28432893
else
28442894
mono_mb_emit_ldloc (mb, tmp_locals [i]);
2845-
}
2846-
else
2847-
mono_mb_emit_ldarg (mb, i);
2895+
} else
2896+
mono_mb_emit_ldarg (mb, csig_argnum);
28482897
}
28492898

28502899
/* ret = method (...) */

src/mono/mono/metadata/marshal.c

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4103,6 +4103,8 @@ marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, Mono
41034103
int i;
41044104
EmitMarshalContext m;
41054105
gboolean marshalling_enabled = FALSE;
4106+
int *swift_sig_to_csig_mp = NULL;
4107+
SwiftPhysicalLowering *swift_lowering = NULL;
41064108

41074109
g_assert (method != NULL);
41084110
error_init (error);
@@ -4183,6 +4185,50 @@ marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, Mono
41834185
csig->hasthis = 0;
41844186
csig->pinvoke = 1;
41854187

4188+
if (invoke)
4189+
mono_marshal_set_callconv_from_modopt (invoke, csig, TRUE);
4190+
else
4191+
mono_marshal_set_callconv_from_unmanaged_callers_only_attribute (method, csig);
4192+
4193+
if (mono_method_signature_has_ext_callconv (csig, MONO_EXT_CALLCONV_SWIFTCALL)) {
4194+
MonoClass *swift_self = mono_class_try_get_swift_self_class ();
4195+
MonoClass *swift_error = mono_class_try_get_swift_error_class ();
4196+
MonoClass *swift_indirect_result = mono_class_try_get_swift_indirect_result_class ();
4197+
swift_lowering = g_newa (SwiftPhysicalLowering, sig->param_count);
4198+
swift_sig_to_csig_mp = g_newa (int, sig->param_count);
4199+
GArray *new_params = g_array_sized_new (FALSE, FALSE, sizeof (MonoType*), csig->param_count);
4200+
int new_param_count = 0;
4201+
4202+
4203+
for (i = 0; i < csig->param_count; i++) {
4204+
swift_lowering [i] = (SwiftPhysicalLowering){0};
4205+
swift_sig_to_csig_mp [i] = new_param_count;
4206+
MonoType *ptype = csig->params [i];
4207+
MonoClass *klass = mono_class_from_mono_type_internal (ptype);
4208+
4209+
if (mono_type_is_struct (ptype) && !(klass == swift_self || klass == swift_error || klass == swift_indirect_result)) {
4210+
SwiftPhysicalLowering lowered_swift_struct = mono_marshal_get_swift_physical_lowering (ptype, FALSE);
4211+
swift_lowering [i] = lowered_swift_struct;
4212+
if (!lowered_swift_struct.by_reference) {
4213+
for (uint32_t idx_lowered = 0; idx_lowered < lowered_swift_struct.num_lowered_elements; idx_lowered++) {
4214+
g_array_append_val (new_params, lowered_swift_struct.lowered_elements [idx_lowered]);
4215+
new_param_count++;
4216+
}
4217+
} else {
4218+
ptype = mono_class_get_byref_type (klass);
4219+
g_array_append_val (new_params, ptype);
4220+
new_param_count++;
4221+
}
4222+
} else {
4223+
g_array_append_val (new_params, ptype);
4224+
new_param_count++;
4225+
}
4226+
}
4227+
4228+
csig = mono_metadata_signature_dup_new_params (NULL, m_method_get_mem_manager (method), csig, new_param_count, (MonoType**)new_params->data);
4229+
g_array_free (new_params, TRUE);
4230+
}
4231+
41864232
if (!marshalling_enabled)
41874233
csig->marshalling_disabled = 1;
41884234

@@ -4194,11 +4240,8 @@ marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, Mono
41944240
m.csig = csig;
41954241
m.image = get_method_image (method);
41964242
m.runtime_marshalling_enabled = marshalling_enabled;
4197-
4198-
if (invoke)
4199-
mono_marshal_set_callconv_from_modopt (invoke, csig, TRUE);
4200-
else
4201-
mono_marshal_set_callconv_from_unmanaged_callers_only_attribute(method, csig);
4243+
m.swift_lowering = swift_lowering;
4244+
m.swift_sig_to_csig_mp = swift_sig_to_csig_mp;
42024245

42034246
/* The attribute is only available in Net 2.0 */
42044247
if (delegate_klass && mono_class_try_get_unmanaged_function_pointer_attribute_class ()) {
@@ -4274,10 +4317,10 @@ marshal_get_managed_wrapper (MonoMethod *method, MonoClass *delegate_klass, Mono
42744317
info->d.native_to_managed.klass = delegate_klass;
42754318

42764319
res = mono_mb_create_and_cache_full (cache, method,
4277-
mb, csig, sig->param_count + 16,
4320+
mb, csig, csig->param_count + 16,
42784321
info, NULL);
42794322
} else {
4280-
res = mono_mb_create (mb, csig, sig->param_count + 16, NULL);
4323+
res = mono_mb_create (mb, csig, csig->param_count + 16, NULL);
42814324
}
42824325
}
42834326

src/mono/mono/metadata/marshal.h

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,16 @@ typedef const gunichar2 *mono_bstr_const;
3737

3838
GENERATE_TRY_GET_CLASS_WITH_CACHE_DECL(stringbuilder)
3939

40+
typedef struct {
41+
gboolean by_reference;
42+
uint32_t num_lowered_elements;
43+
MonoType *lowered_elements[4];
44+
uint32_t offsets[4];
45+
} SwiftPhysicalLowering;
46+
47+
SwiftPhysicalLowering
48+
mono_marshal_get_swift_physical_lowering (MonoType *type, gboolean native_layout);
49+
4050

4151
/*
4252
* This structure holds the state kept by the emit_ marshalling functions.
@@ -53,6 +63,8 @@ typedef struct {
5363
MonoMethodSignature *csig; /* Might need to be changed due to MarshalAs directives */
5464
MonoImage *image; /* The image to use for looking up custom marshallers */
5565
gboolean runtime_marshalling_enabled;
66+
SwiftPhysicalLowering *swift_lowering;
67+
int *swift_sig_to_csig_mp;
5668
} EmitMarshalContext;
5769

5870
typedef enum {
@@ -744,14 +756,4 @@ GENERATE_TRY_GET_CLASS_WITH_CACHE_DECL (swift_self)
744756
GENERATE_TRY_GET_CLASS_WITH_CACHE_DECL (swift_error)
745757
GENERATE_TRY_GET_CLASS_WITH_CACHE_DECL (swift_indirect_result)
746758

747-
typedef struct {
748-
gboolean by_reference;
749-
uint32_t num_lowered_elements;
750-
MonoType *lowered_elements[4];
751-
uint32_t offsets[4];
752-
} SwiftPhysicalLowering;
753-
754-
SwiftPhysicalLowering
755-
mono_marshal_get_swift_physical_lowering (MonoType *type, gboolean native_layout);
756-
757759
#endif /* __MONO_MARSHAL_H__ */

0 commit comments

Comments
 (0)