diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/FunctionPointerTests.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/FunctionPointerTests.cs index fde6b235ed4561..7557cf2e51921f 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/FunctionPointerTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/FunctionPointerTests.cs @@ -115,5 +115,17 @@ static int CallbackUnmanagedStdcall(int a, int b) return Callback(a, b); } } + + [UnmanagedCallersOnly] + public static int Increment (int i) { + return i + 1; + } + + [Fact] + public unsafe void CalliUnmanaged() + { + delegate* unmanaged callbackProc = (delegate* unmanaged)&Increment; + Assert.Equal(6, callbackProc(5)); + } } } diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index d810a5a8c67829..db28b53d3483bd 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -3797,17 +3797,11 @@ mono_marshal_get_native_func_wrapper_indirect (MonoClass *caller_class, MonoMeth if ((res = mono_marshal_find_in_cache (cache, sig))) return res; -#if 0 - fprintf (stderr, "generating wrapper for signature %s\n", mono_signature_full_name (sig)); -#endif - - /* FIXME: better wrapper name */ - char * name = g_strdup_printf ("wrapper_native_indirect_%p", sig); + char *name = mono_signature_to_name (sig, "wrapper_native_indirect"); MonoMethodBuilder *mb = mono_mb_new (caller_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE); mb->method->save_lmf = 1; WrapperInfo *info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NATIVE_FUNC_INDIRECT); - //info->d.managed_to_native.method = NULL; info->d.native_func.klass = caller_class; info->d.native_func.sig = sig; @@ -3819,6 +3813,7 @@ mono_marshal_get_native_func_wrapper_indirect (MonoClass *caller_class, MonoMeth mono_marshal_emit_native_wrapper (image, mb, sig, piinfo, mspecs, /*func*/NULL, flags); g_free (mspecs); + /* Add an extra argument which the caller will use to pass in the ftnptr to call */ MonoMethodSignature *csig = mono_metadata_signature_dup_add_this (image, sig, mono_defaults.int_class); csig->pinvoke = 0; diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 107507498be330..a66448177eb0ce 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -9274,6 +9274,13 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method) add_gsharedvt_wrappers (acfg, mono_method_signature_internal (cfg->method), FALSE, TRUE, TRUE); } + for (GSList *l = cfg->pinvoke_calli_signatures; l; l = l->next) { + MonoMethodSignature *sig = mono_metadata_signature_dup ((MonoMethodSignature*)l->data); + + MonoMethod *wrapper = mono_marshal_get_native_func_wrapper_indirect (cfg->method->klass, sig, TRUE); + add_extra_method (acfg, wrapper); + } + if (cfg->llvm_only) acfg->stats.llvm_count ++; @@ -9709,6 +9716,9 @@ append_mangled_wrapper_subtype (GString *s, WrapperSubtype subtype) case WRAPPER_SUBTYPE_LLVM_FUNC: label = "llvm_func"; break; + case WRAPPER_SUBTYPE_NATIVE_FUNC_INDIRECT: + label = "native_func_indirect"; + break; default: g_assert_not_reached (); } @@ -9872,6 +9882,9 @@ append_mangled_wrapper (GString *s, MonoMethod *method) append_sig = FALSE; } else if (info->subtype == WRAPPER_SUBTYPE_NATIVE_FUNC_AOT) { success = success && append_mangled_method (s, info->d.managed_to_native.method); + } else if (info->subtype == WRAPPER_SUBTYPE_NATIVE_FUNC_INDIRECT) { + append_mangled_signature (s, info->d.native_func.sig); + append_sig = FALSE; } else { g_assert (info->subtype == WRAPPER_SUBTYPE_NONE || info->subtype == WRAPPER_SUBTYPE_PINVOKE); success = success && append_mangled_method (s, info->d.managed_to_native.method); diff --git a/src/mono/mono/mini/method-to-ir.c b/src/mono/mono/mini/method-to-ir.c index c00b9d6cd1018f..e3719b1e5a7f1a 100644 --- a/src/mono/mono/mini/method-to-ir.c +++ b/src/mono/mono/mini/method-to-ir.c @@ -7306,6 +7306,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b #if 0 fprintf (stderr, "generating wrapper for calli in method %s with wrapper type %s\n", method->name, mono_wrapper_type_to_str (method->wrapper_type)); #endif + + if (cfg->compile_aot) + cfg->pinvoke_calli_signatures = g_slist_prepend_mempool (cfg->mempool, cfg->pinvoke_calli_signatures, fsig); + /* Call the wrapper that will do the GC transition instead */ MonoMethod *wrapper = mono_marshal_get_native_func_wrapper_indirect (method->klass, fsig, cfg->compile_aot); diff --git a/src/mono/mono/mini/mini.h b/src/mono/mono/mini/mini.h index 3d02bd18a0230c..3a94052307ad5c 100644 --- a/src/mono/mono/mini/mini.h +++ b/src/mono/mono/mini/mini.h @@ -1609,6 +1609,7 @@ typedef struct { GSList *signatures; GSList *interp_in_signatures; + GSList *pinvoke_calli_signatures; /* GC Maps */