diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index 4102d4c7711150..32506047d2269d 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -6268,6 +6268,18 @@ void CodeGen::genCallInstruction(GenTreeCall* call X86_ARG(target_ssize_t stackA { retSize = emitTypeSize(retTypeDesc->GetReturnRegType(0)); secondRetSize = emitTypeSize(retTypeDesc->GetReturnRegType(1)); + + if (retTypeDesc->GetABIReturnReg(1, call->GetUnmanagedCallConv()) == REG_INTRET) + { + // If the second return register is REG_INTRET, then the first + // return is expected to be in a SIMD register. + // The emitter has hardcoded belief that retSize corresponds to + // REG_INTRET and secondRetSize to REG_INTRET_1, so fix up the + // situation here. + assert(!EA_IS_GCREF_OR_BYREF(retSize)); + retSize = secondRetSize; + secondRetSize = EA_UNKNOWN; + } } else { diff --git a/src/coreclr/jit/gcencode.cpp b/src/coreclr/jit/gcencode.cpp index ae05bf797f86ab..a1e9f935327d37 100644 --- a/src/coreclr/jit/gcencode.cpp +++ b/src/coreclr/jit/gcencode.cpp @@ -49,8 +49,21 @@ ReturnKind GCInfo::getReturnKind() case 1: return VarTypeToReturnKind(retTypeDesc.GetReturnRegType(0)); case 2: - return GetStructReturnKind(VarTypeToReturnKind(retTypeDesc.GetReturnRegType(0)), - VarTypeToReturnKind(retTypeDesc.GetReturnRegType(1))); + { + var_types first = retTypeDesc.GetReturnRegType(0); + var_types second = retTypeDesc.GetReturnRegType(1); +#ifdef UNIX_AMD64_ABI + if (varTypeUsesFloatReg(first)) + { + // first does not consume an int register in this case so an obj/ref + // in the second ReturnKind would actually be found in the first int reg. + first = second; + second = TYP_UNDEF; + } +#endif // UNIX_AMD64_ABI + return GetStructReturnKind(VarTypeToReturnKind(first), + VarTypeToReturnKind(second)); + } default: #ifdef DEBUG for (unsigned i = 0; i < regCount; i++) diff --git a/src/coreclr/vm/method.cpp b/src/coreclr/vm/method.cpp index 8b7239896a0ea6..5bb965cce056f1 100644 --- a/src/coreclr/vm/method.cpp +++ b/src/coreclr/vm/method.cpp @@ -1324,6 +1324,15 @@ ReturnKind MethodDesc::ParseReturnKindFromSig(INDEBUG(bool supportStringConstruc regKinds[i] = RT_Scalar; } } + + if (eeClass->GetEightByteClassification(0) == SystemVClassificationTypeSSE) + { + // Skip over SSE types since they do not consume integer registers. + // An obj/byref in the 2nd eight bytes will be in the first integer register. + regKinds[0] = regKinds[1]; + regKinds[1] = RT_Scalar; + } + ReturnKind structReturnKind = GetStructReturnKind(regKinds[0], regKinds[1]); return structReturnKind; } diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_115815/Runtime_115815.cs b/src/tests/JIT/Regression/JitBlue/Runtime_115815/Runtime_115815.cs new file mode 100644 index 00000000000000..77f42fe7d49453 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_115815/Runtime_115815.cs @@ -0,0 +1,42 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Threading; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using Xunit; + +public class Runtime_115815 +{ + [Fact] + public static void TestEntryPoint() + { + var destination = new KeyValuePair[1_000]; + + // loop to make this method fully interruptible + to get into OSR version + for (int i = 0; i < destination.Length * 1000; i++) + { + destination[i / 1000] = default; + } + + for (int i = 0; i < 5; i++) + { + for (int j = 0; j < destination.Length; j++) + { + destination[j] = GetValue(j); + } + + Thread.Sleep(10); + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static KeyValuePair GetValue(int i) + => KeyValuePair.Create(new Container(i.ToString()), (double)i); + + private struct Container + { + public string Name; + public Container(string name) { this.Name = name; } + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_115815/Runtime_115815.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_115815/Runtime_115815.csproj new file mode 100644 index 00000000000000..de6d5e08882e86 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_115815/Runtime_115815.csproj @@ -0,0 +1,8 @@ + + + True + + + + +