From b3330408dbb0b5891d7378354b5851012d0e1b3b Mon Sep 17 00:00:00 2001 From: Andy Ayers Date: Fri, 10 Jul 2020 14:09:03 -0700 Subject: [PATCH] JIT: retype byrefs passed to unmanaged callers as native int 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 | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/coreclr/src/jit/importer.cpp b/src/coreclr/src/jit/importer.cpp index ee8a326e52e9d4..ca5afe54a1770e 100644 --- a/src/coreclr/src/jit/importer.cpp +++ b/src/coreclr/src/jit/importer.cpp @@ -6881,14 +6881,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; } }