JIT: retype byrefs passed to unmanaged callers as native int (#39105)
authorAndy Ayers <andya@microsoft.com>
Sat, 11 Jul 2020 17:37:06 +0000 (10:37 -0700)
committerGitHub <noreply@github.com>
Sat, 11 Jul 2020 17:37:06 +0000 (10:37 -0700)
Make the jit more robust in cases where the IL producer is passing a byref
to an unmanaged caller, by retyping the argument as native int.

Allows the jit to produce self-consistent GC info and avoid the issues
seen in #34279, at least for byrefs.

Closes #39040.

src/coreclr/src/jit/importer.cpp

index 7137acc..10b7607 100644 (file)
@@ -6921,14 +6921,27 @@ void Compiler::impPopArgsForUnmanagedCall(GenTree* call, CORINFO_SIG_INFO* sig)
 
     for (GenTreeCall::Use& argUse : GenTreeCall::UseList(args))
     {
-        // We should not be passing gc typed args to an unmanaged call.
         GenTree* arg = argUse.GetNode();
+        call->gtFlags |= arg->gtFlags & GTF_GLOB_EFFECT;
+
+        // We should not be passing gc typed args to an unmanaged call.
         if (varTypeIsGC(arg->TypeGet()))
         {
-            assert(!"*** invalid IL: gc type passed to unmanaged call");
+            // Tolerate byrefs by retyping to native int.
+            //
+            // This is needed or we'll generate inconsistent GC info
+            // for this arg at the call site (gc info says byref,
+            // pinvoke sig says native int).
+            //
+            if (arg->TypeGet() == TYP_BYREF)
+            {
+                arg->ChangeType(TYP_I_IMPL);
+            }
+            else
+            {
+                assert(!"*** invalid IL: gc ref passed to unmanaged call");
+            }
         }
-
-        call->gtFlags |= arg->gtFlags & GTF_GLOB_EFFECT;
     }
 }