From 72d8e627b25b0359fcea14568d03111ece37c742 Mon Sep 17 00:00:00 2001 From: Milos Kotlar Date: Fri, 15 May 2026 15:59:32 +0200 Subject: [PATCH] [clr-interp] Detect Swift calling convention for transient-IL P/Invokes After P/Invokes were converted to transient IL (#126509), the P/Invoke MethodDesc itself carries the IL with the calli to the native target. MethodDesc::IsILStub() returns true only for DynamicMethodDesc, so the Swift detection in CInterpreterJitInfo::GetCookieForInterpreterCalliSig from #125177 leaves pContextMD NULL for transient-IL P/Invokes. ComputeCallStub cannot then detect the Swift calling convention, never runs RewriteSignatureForSwiftLowering, and emits a stub that does not preserve x21. SwiftError is lost on return, and the multiple-SwiftError InvalidProgramException validation is skipped. Pass the method-being-compiled as pContextMD when it is a P/Invoke. The existing IsPInvoke branch in ComputeCallStub then resolves the unmanaged calling convention via PInvoke::GetCallingConvention_IgnoreErrors. Fixes #127897 Fixes #127898 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/coreclr/vm/jitinterface.cpp | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 104bfc701e4872..5310997c3beb9b 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -11506,18 +11506,24 @@ LPVOID CInterpreterJitInfo::GetCookieForInterpreterCalliSig(CORINFO_SIG_INFO* sz InterpreterCalliCookie result = NULL; JIT_TO_EE_TRANSITION(); - // When compiling a calli inside an IL stub for a P/Invoke, pass the target - // P/Invoke MethodDesc so ComputeCallStub can detect the Swift calling convention. - // Do not cache the cookie on pContextMD: MethodDesc::CalliCookie is for - // calling the target via managed calling convention. The stub we are about - // to generate calls the target via unmanaged calling convention. + // Pass the target P/Invoke MethodDesc as pContextMD so ComputeCallStub can + // detect the Swift calling convention. Do not cache the cookie on pContextMD: + // MethodDesc::CalliCookie is for the managed calling convention; the stub + // we generate calls the target via unmanaged calling convention. MethodDesc* pContextMD = nullptr; - if (m_pMethodBeingCompiled != nullptr && m_pMethodBeingCompiled->IsILStub()) + if (m_pMethodBeingCompiled != nullptr) { - MethodDesc* pTargetMD = m_pMethodBeingCompiled->AsDynamicMethodDesc()->GetILStubResolver()->GetStubTargetMethodDesc(); - if (pTargetMD != nullptr) + if (m_pMethodBeingCompiled->IsILStub()) { - pContextMD = pTargetMD; + MethodDesc* pTargetMD = m_pMethodBeingCompiled->AsDynamicMethodDesc()->GetILStubResolver()->GetStubTargetMethodDesc(); + if (pTargetMD != nullptr) + { + pContextMD = pTargetMD; + } + } + else if (m_pMethodBeingCompiled->IsPInvoke()) + { + pContextMD = m_pMethodBeingCompiled; } }