[mono][aot] Generate 'native-indirect' wrappers in full-aot mode. (#85923)
authorZoltan Varga <vargaz@gmail.com>
Tue, 9 May 2023 21:30:30 +0000 (14:30 -0700)
committerGitHub <noreply@github.com>
Tue, 9 May 2023 21:30:30 +0000 (14:30 -0700)
Fixes https://github.com/dotnet/runtime/issues/80853.

src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/FunctionPointerTests.cs
src/mono/mono/metadata/marshal.c
src/mono/mono/mini/aot-compiler.c
src/mono/mono/mini/method-to-ir.c
src/mono/mono/mini/mini.h

index fde6b23..7557cf2 100644 (file)
@@ -115,5 +115,17 @@ namespace LibraryImportGenerator.IntegrationTests
                 return Callback(a, b);
             }
         }
+
+        [UnmanagedCallersOnly]
+        public static int Increment (int i) {
+            return i + 1;
+        }
+
+        [Fact]
+        public unsafe void CalliUnmanaged()
+        {
+            delegate* unmanaged<int, int> callbackProc = (delegate* unmanaged<int, int>)&Increment;
+            Assert.Equal(6, callbackProc(5));
+        }
     }
 }
index 977ecd9..61cc96b 100644 (file)
@@ -3867,17 +3867,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;
 
@@ -3889,6 +3883,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;
 
index 124fa7a..d1ed5a9 100644 (file)
@@ -9659,6 +9659,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 ++;
 
index 9e67f99..3e84e55 100644 (file)
@@ -7471,6 +7471,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);
 
index a21e3c3..055d6dc 100644 (file)
@@ -1629,6 +1629,7 @@ typedef struct {
 
        GSList *signatures;
        GSList *interp_in_signatures;
+       GSList *pinvoke_calli_signatures;
 
        /* GC Maps */