From: Clinton Ingram Date: Sat, 23 Feb 2019 17:06:16 +0000 (-0800) Subject: fix BSWAP16 intrinsic handling of signed values (#22666) X-Git-Tag: accepted/tizen/unified/20190813.215958~61^2~153 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=56da27b66c9463f0a28b2427aabbe2af0614efdc;p=platform%2Fupstream%2Fcoreclr.git fix BSWAP16 intrinsic handling of signed values (#22666) --- diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp index 5d3a82e..6f19213 100644 --- a/src/jit/importer.cpp +++ b/src/jit/importer.cpp @@ -4068,7 +4068,8 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis, { case CorInfoType::CORINFO_TYPE_SHORT: case CorInfoType::CORINFO_TYPE_USHORT: - retNode = gtNewOperNode(GT_BSWAP16, callType, impPopStack().val); + retNode = gtNewCastNode(TYP_INT, gtNewOperNode(GT_BSWAP16, TYP_INT, impPopStack().val), false, + callType); break; case CorInfoType::CORINFO_TYPE_INT: diff --git a/tests/src/JIT/Intrinsics/BinaryPrimitivesReverseEndianness.cs b/tests/src/JIT/Intrinsics/BinaryPrimitivesReverseEndianness.cs index b650fc8..a1a2f74 100644 --- a/tests/src/JIT/Intrinsics/BinaryPrimitivesReverseEndianness.cs +++ b/tests/src/JIT/Intrinsics/BinaryPrimitivesReverseEndianness.cs @@ -5,6 +5,7 @@ using System; using System.Buffers.Binary; +using System.Runtime.InteropServices; using Internal; namespace BinaryPrimitivesReverseEndianness @@ -23,6 +24,8 @@ namespace BinaryPrimitivesReverseEndianness private const ulong ConstantUInt64Input = 0xfedcba9876543210; private const ulong ConstantUInt64Expected = 0x1032547698badcfe; + private static readonly byte[] s_bufferLE = new byte[] { 0x32, 0x54, 0x76, 0x98 }; + private static readonly byte[] s_bufferBE = new byte[] { 0x98, 0x76, 0x54, 0x32 }; static int Main(string[] args) { @@ -33,28 +36,42 @@ namespace BinaryPrimitivesReverseEndianness ushort swappedUInt16 = BinaryPrimitives.ReverseEndianness(ConstantUInt16Input); if (swappedUInt16 != ConstantUInt16Expected) { - Console.WriteLine($"BinaryPrimitives.ReverseEndianness(const UInt16) failed."); - Console.WriteLine($"Input: 0x{ConstantUInt16Input:X4}"); - Console.WriteLine($"Output: 0x{swappedUInt16:X4}"); - Console.WriteLine($"Expected: 0x{ConstantUInt16Expected:X4}"); + ReportError("const UInt16", ConstantUInt16Input, swappedUInt16, ConstantUInt16Expected); + return Fail; } uint swappedUInt32 = BinaryPrimitives.ReverseEndianness(ConstantUInt32Input); if (swappedUInt32 != ConstantUInt32Expected) { - Console.WriteLine($"BinaryPrimitives.ReverseEndianness(const UInt32) failed."); - Console.WriteLine($"Input: 0x{ConstantUInt32Input:X8}"); - Console.WriteLine($"Output: 0x{swappedUInt32:X8}"); - Console.WriteLine($"Expected: 0x{ConstantUInt32Expected:X8}"); + ReportError("const UInt32", ConstantUInt32Input, swappedUInt32, ConstantUInt32Expected); + return Fail; } ulong swappedUInt64 = BinaryPrimitives.ReverseEndianness(ConstantUInt64Input); if (swappedUInt64 != ConstantUInt64Expected) { - Console.WriteLine($"BinaryPrimitives.ReverseEndianness(const UInt32) failed."); - Console.WriteLine($"Input: 0x{ConstantUInt64Input:X16}"); - Console.WriteLine($"Output: 0x{swappedUInt64:X16}"); - Console.WriteLine($"Expected: 0x{ConstantUInt64Expected:X16}"); + ReportError("const UInt64", ConstantUInt64Input, swappedUInt64, ConstantUInt64Expected); + return Fail; + } + + /* + * SIGN-EXTENDED VALUE TESTS + */ + + Span spanInt16 = BitConverter.IsLittleEndian ? s_bufferLE.AsSpan().Slice(2) : s_bufferBE; + short swappedInt16 = BinaryPrimitives.ReverseEndianness(MemoryMarshal.Read(spanInt16)); + if (swappedInt16 != ConstantUInt16Expected) + { + ReportError("sign-extended Int16", ConstantUInt16Input, (int)swappedInt16, ConstantUInt16Expected); + return Fail; + } + + Span spanInt32 = BitConverter.IsLittleEndian ? s_bufferLE : s_bufferBE; + int swappedInt32 = BinaryPrimitives.ReverseEndianness(MemoryMarshal.Read(spanInt32)); + if (swappedInt32 != ConstantUInt32Expected) + { + ReportError("sign-extended Int32", ConstantUInt32Input, (long)swappedInt32, ConstantUInt32Expected); + return Fail; } /* @@ -66,10 +83,8 @@ namespace BinaryPrimitivesReverseEndianness ushort nonConstUInt16Expected = ByteSwapUInt16_Control(nonConstUInt16Input); if (nonConstUInt16Output != nonConstUInt16Expected) { - Console.WriteLine($"BinaryPrimitives.ReverseEndianness(non-const UInt16) failed."); - Console.WriteLine($"Input: 0x{nonConstUInt16Input:X4}"); - Console.WriteLine($"Output: 0x{nonConstUInt16Output:X4}"); - Console.WriteLine($"Expected: 0x{nonConstUInt16Expected:X4}"); + ReportError("non-const UInt16", nonConstUInt16Input, nonConstUInt16Output, nonConstUInt16Expected); + return Fail; } uint nonConstUInt32Input = (uint)DateTime.UtcNow.Ticks; @@ -77,10 +92,8 @@ namespace BinaryPrimitivesReverseEndianness uint nonConstUInt32Expected = ByteSwapUInt32_Control(nonConstUInt32Input); if (nonConstUInt32Output != nonConstUInt32Expected) { - Console.WriteLine($"BinaryPrimitives.ReverseEndianness(non-const UInt32) failed."); - Console.WriteLine($"Input: 0x{nonConstUInt32Input:X8}"); - Console.WriteLine($"Output: 0x{nonConstUInt32Output:X8}"); - Console.WriteLine($"Expected: 0x{nonConstUInt32Expected:X8}"); + ReportError("non-const UInt32", nonConstUInt32Input, nonConstUInt32Output, nonConstUInt32Expected); + return Fail; } ulong nonConstUInt64Input = (ulong)DateTime.UtcNow.Ticks; @@ -88,10 +101,8 @@ namespace BinaryPrimitivesReverseEndianness ulong nonConstUInt64Expected = ByteSwapUInt64_Control(nonConstUInt64Input); if (nonConstUInt64Output != nonConstUInt64Expected) { - Console.WriteLine($"BinaryPrimitives.ReverseEndianness(non-const UInt64) failed."); - Console.WriteLine($"Input: 0x{nonConstUInt64Input:X16}"); - Console.WriteLine($"Output: 0x{nonConstUInt64Output:X16}"); - Console.WriteLine($"Expected: 0x{nonConstUInt64Expected:X16}"); + ReportError("non-const UInt64", nonConstUInt64Input, nonConstUInt64Output, nonConstUInt64Expected); + return Fail; } return Pass; @@ -132,5 +143,32 @@ namespace BinaryPrimitivesReverseEndianness return retVal; } + + private static string GetHexString(T value) + { + if (typeof(T) == typeof(short)) + return ((short)(object)value).ToString("X4"); + if (typeof(T) == typeof(ushort)) + return ((ushort)(object)value).ToString("X4"); + if (typeof(T) == typeof(int)) + return ((int)(object)value).ToString("X8"); + if (typeof(T) == typeof(uint)) + return ((uint)(object)value).ToString("X8"); + if (typeof(T) == typeof(long)) + return ((long)(object)value).ToString("X16"); + if (typeof(T) == typeof(ulong)) + return ((ulong)(object)value).ToString("X16"); + + throw new NotSupportedException(); + } + + private static void ReportError(string testName, T input, T output, T expected) + { + Console.WriteLine($"BinaryPrimitives.ReverseEndianness({testName}) failed."); + Console.WriteLine($"Input: 0x{GetHexString(input)}"); + Console.WriteLine($"Output: 0x{GetHexString(output)}"); + Console.WriteLine($"Expected: 0x{GetHexString(expected)}"); + } + } }