From: Andy Ayers Date: Fri, 29 Jun 2018 16:32:44 +0000 (-0700) Subject: JIT: fix regression when returning struct with no fields on SysV (#18708) X-Git-Tag: accepted/tizen/unified/20190422.045933~1790 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=65d31999eb89e11a74fe8cbf25982a3ed33a564f;p=platform%2Fupstream%2Fcoreclr.git JIT: fix regression when returning struct with no fields on SysV (#18708) The runtime classifies such structs as being returned by reference, so we need to follow suit in the jit. If the classifier says the value can't be returned in a register, then so be it. Add a test case. --- diff --git a/src/jit/compiler.cpp b/src/jit/compiler.cpp index 5e8088d..170cf38 100644 --- a/src/jit/compiler.cpp +++ b/src/jit/compiler.cpp @@ -992,8 +992,9 @@ var_types Compiler::getReturnTypeForStruct(CORINFO_CLASS_HANDLE clsHnd, structPassingKind* wbReturnStruct /* = nullptr */, unsigned structSize /* = 0 */) { - var_types useType = TYP_UNKNOWN; - structPassingKind howToReturnStruct = SPK_Unknown; // We must change this before we return + var_types useType = TYP_UNKNOWN; + structPassingKind howToReturnStruct = SPK_Unknown; // We must change this before we return + bool canReturnInRegister = true; assert(clsHnd != NO_CLASS_HANDLE); @@ -1013,6 +1014,7 @@ var_types Compiler::getReturnTypeForStruct(CORINFO_CLASS_HANDLE clsHnd, if (structDesc.eightByteCount == 1) { assert(structSize <= sizeof(double)); + assert(structDesc.passedInRegisters); if (structDesc.eightByteClassifications[0] == SystemVClassificationTypeSSE) { @@ -1022,6 +1024,11 @@ var_types Compiler::getReturnTypeForStruct(CORINFO_CLASS_HANDLE clsHnd, howToReturnStruct = SPK_PrimitiveType; } } + else + { + // Return classification is not always size based... + canReturnInRegister = structDesc.passedInRegisters; + } #endif // UNIX_AMD64_ABI @@ -1031,7 +1038,7 @@ var_types Compiler::getReturnTypeForStruct(CORINFO_CLASS_HANDLE clsHnd, // The largest primitive type is 8 bytes (TYP_DOUBLE) // so we can skip calling getPrimitiveTypeForStruct when we // have a struct that is larger than that. - if ((useType == TYP_UNKNOWN) && (structSize <= sizeof(double))) + if (canReturnInRegister && (useType == TYP_UNKNOWN) && (structSize <= sizeof(double))) { // We set the "primitive" useType based upon the structSize // and also examine the clsHnd to see if it is an HFA of count one diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_8.cs b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_8.cs new file mode 100644 index 0000000..9bd91be --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_8.cs @@ -0,0 +1,65 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.CompilerServices; + +// Based on +// Original generated by Fuzzlyn on 2018-06-20 00:58:58 +// Seed: 11049252875418439527 +// Reduced from 97.5 KiB to 0.5 KiB +// Debug: Outputs -1 +// Release: Outputs -65536 + +// Similar to other variants but using an empty (~ 1 byte) struct +// (which oddly enough currently is returned by ref) + +struct S0 +{ +} + +struct S1 +{ + public S0 F3; + public sbyte F4; + public short F0; + public S1(sbyte f4): this() + { + F4 = f4; + } +} + +public class GitHub_18522_8 +{ + static S1 s_6; + static S1[] s_13 = new S1[]{new S1(-1)}; + public static int Main() + { + // When generating code for the x64 SysV ABI, the jit was + // incorrectly typing the return type from M16, and so + // inadvertently overwriting the F4 field of s_13[0] on return + // from the call. + // + // Here we make sure we properly handle the failed inline case. + s_13[0].F3 = M16(); + return s_13[0].F4 == -1 ? 100 : 0; + } + + static S0 M16() + { + // This bit of code is intended to allow M16 to be an + // inline candidate that ultimately does not get inlined. + short x = 0; + for (int i = 0; i < 10; i++) + { + for (int j = 0; j < 10; j++) + { + x++; + } + } + s_6.F0 = x; + + return s_6.F3; + } +} diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_8.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_8.csproj new file mode 100644 index 0000000..95aba99 --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_18522/GitHub_18522_8.csproj @@ -0,0 +1,34 @@ + + + + + Debug + AnyCPU + $(MSBuildProjectName) + 2.0 + {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + + + + + + + False + + + + + True + + + + + + + + + +