From c5d5da257e9ba9ed3a4cd3191b8165065933b115 Mon Sep 17 00:00:00 2001 From: Alexander Kyte Date: Mon, 1 Jun 2015 18:14:00 +0000 Subject: [PATCH] [runtime] Emit the necessary left shift anding in the LambdaCompiler We were observing dtest-006.exe test failing on armhf. This test checks that a right shift with a negative shift amount and a dynamic base is shifted by the right amount. We were failing it because we were excluding the step that we do in regular code generation, which is to do a binary and of the shift amount so it behaves like we are shifting by the original shift amount modulo 32. The C# spec defines left shift like so. This commit adds that to the LambdaCompiler. --- .../Compiler/LambdaCompiler.Binary.cs | 6 ++ mcs/tests/dtest-061.cs | 63 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 mcs/tests/dtest-061.cs diff --git a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Binary.cs b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Binary.cs index a089b81222d..3c9ec62326e 100644 --- a/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Binary.cs +++ b/mcs/class/dlr/Runtime/Microsoft.Scripting.Core/Compiler/LambdaCompiler.Binary.cs @@ -275,6 +275,12 @@ namespace System.Linq.Expressions.Compiler { if (rightType != typeof(int)) { throw ContractUtils.Unreachable; } + // Note: If this code is made to handle unsigned + // rightType types, emit the following when rightType: + // is unsigned + //_ilg.EmitInt(0x3f); + _ilg.EmitInt(0x1f); + _ilg.Emit(OpCodes.And); _ilg.Emit(OpCodes.Shl); break; case ExpressionType.RightShift: diff --git a/mcs/tests/dtest-061.cs b/mcs/tests/dtest-061.cs new file mode 100644 index 00000000000..de16049239d --- /dev/null +++ b/mcs/tests/dtest-061.cs @@ -0,0 +1,63 @@ +using System; + +namespace Test +{ + public class Program + { + static int[] testValues = {0, -1, 200, -200, 32, -32, 64, -128, 333, 5}; + + dynamic dynBase; + dynamic dynAmt; + + int? optBase; + int? optAmt; + + int normBase; + int normAmt; + + dynamic uDynBase; + + public static void Main () + { + var tester = new Program (); + + foreach (int baseVal in testValues) + foreach (int amt in testValues) + tester.ShiftTest (baseVal, amt); + } + + public static void AreEqual (A a, B b) + { + if (!a.Equals (b)) + throw new Exception ( + String.Format ( + "Shift Equality Assertion Failed: Had {0} and expected {1}", a, b)); + } + + public void ShiftTest (int shiftBase, int shiftAmt) + { + optBase = dynBase = normBase = shiftBase; + optAmt = dynAmt = normAmt = shiftAmt; + int immediate = shiftBase << shiftAmt; + + AreEqual (dynBase << dynAmt, immediate); + AreEqual (dynBase << optAmt, immediate); + AreEqual (dynBase << normAmt, immediate); + + AreEqual (optBase << dynAmt, immediate); + AreEqual (optBase << optAmt, immediate); + AreEqual (optBase << normAmt, immediate); + + AreEqual (normBase << dynAmt, immediate); + AreEqual (normBase << optAmt, immediate); + AreEqual (normBase << normAmt, immediate); + + uint uShiftBase = (uint)shiftBase; + uDynBase = uShiftBase; + + AreEqual (uShiftBase << dynAmt, uDynBase << dynAmt); + AreEqual (uShiftBase << optAmt, uDynBase << optAmt); + AreEqual (uShiftBase << normAmt, uDynBase << normAmt); + } + } +} -- 2.25.1