[release/6.0] Restore FP pairs when unwinding in ARM64 (#69359)
authorJuan Hoyos <juan.hoyos@microsoft.com>
Mon, 16 May 2022 22:09:18 +0000 (15:09 -0700)
committerGitHub <noreply@github.com>
Mon, 16 May 2022 22:09:18 +0000 (15:09 -0700)
* Add regression test
* Restore FP pairs when unwinding in ARM64
* Disable windows arm64 version of the test

src/coreclr/unwinder/arm64/unwinder_arm64.cpp
src/tests/Exceptions/UnwindFpBleedTest/UnwindFpBleedTest.cs [new file with mode: 0644]
src/tests/Exceptions/UnwindFpBleedTest/UnwindFpBleedTest.csproj [new file with mode: 0644]
src/tests/issues.targets

index 5740c3cfcab80cacc5e46ca38c714283b0ba9556..e2e1c512ee6cc3ab6c2b42acbce09e0da047aabb 100644 (file)
@@ -1038,7 +1038,7 @@ ExecuteCodes:
                         ContextRecord,
                         8 * (NextCode & 0x3f),
                         8 + ((CurCode & 1) << 2) + (NextCode >> 6),
-                        2 + AccumulatedSaveNexts,
+                        2 + 2 * AccumulatedSaveNexts,
                         UnwindParams);
             AccumulatedSaveNexts = 0;
         }
@@ -1054,7 +1054,7 @@ ExecuteCodes:
                         ContextRecord,
                         -8 * ((NextCode & 0x3f) + 1),
                         8 + ((CurCode & 1) << 2) + (NextCode >> 6),
-                        2 + AccumulatedSaveNexts,
+                        2 + 2 * AccumulatedSaveNexts,
                         UnwindParams);
             AccumulatedSaveNexts = 0;
         }
diff --git a/src/tests/Exceptions/UnwindFpBleedTest/UnwindFpBleedTest.cs b/src/tests/Exceptions/UnwindFpBleedTest/UnwindFpBleedTest.cs
new file mode 100644 (file)
index 0000000..2240d3f
--- /dev/null
@@ -0,0 +1,82 @@
+using System;
+using System.Runtime.CompilerServices;
+
+class Program
+{
+    static int Main()
+    {
+        double a0 = 1.0;
+        double a1 = 2.0;
+        double a2 = 3.0;
+        double a3 = 4.0;
+        double a4 = 5.0;
+        double a5 = 6.0;
+        double a6 = 7.0;
+        double a7 = 8.0;
+        double a8 = 9.0;
+        double a9 = 10.0;
+
+        for (int i = 1; i < 10; i++)
+        {
+            a0 *= 1.0;
+            a1 *= 2.0;
+            a2 *= 3.0;
+            a3 *= 4.0;
+            a4 *= 5.0;
+            a5 *= 6.0;
+            a6 *= 7.0;
+            a7 *= 8.0;
+            a8 *= 9.0;
+            a9 *= 10.0;
+        }
+
+        EHMethod();
+
+        bool isExpectedValue =
+            a0 == 1.0
+            && a1 == Math.Pow(2, 10)
+            && a2 == Math.Pow(3, 10)
+            && a3 == Math.Pow(4, 10)
+            && a4 == Math.Pow(5, 10)
+            && a5 == Math.Pow(6, 10)
+            && a6 == Math.Pow(7, 10)
+            && a7 == Math.Pow(8, 10)
+            && a8 == Math.Pow(9, 10)
+            && a9 == Math.Pow(10, 10);
+
+        return isExpectedValue ? 100 : 1;
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    static void EHMethod()
+    {
+        try
+        {
+            FloatManipulationMethod();
+        }
+        catch (Exception) { }
+    }
+
+    [MethodImpl(MethodImplOptions.NoInlining)]
+    static void FloatManipulationMethod()
+    {
+        // Enough locals to try to get the JIT to touch at least some of the non-volatile
+        // registers (some spilling might happen, but hopefully the lack of EH prioritizes
+        // registers).
+        double a0 = 1, a1 = 2, a2 = 3, a3 = 4, a4 = 5, a5 = 6, a6 = 7, a7 = 8;
+        double a8 = 1, a9 = 2, a10 = 3, a11 = 4, a12 = 5, a13 = 6, a14 = 7, a15 = 8;
+        double a16 = 1, a17 = 2, a18 = 3, a19 = 4, a20 = 5, a21 = 6, a22 = 7, a23 = 8;
+        double a24 = 1, a25 = 2, a26 = 3, a27 = 4, a28 = 5, a29 = 6, a30 = 7, a31 = 8;
+
+        // Some busy math to prevent easy optimizations and folding.
+        for (int i = 0; i < 5; i++)
+        {
+            a0 -= 1; a1 -= 2; a2 -= 3; a3 -= 4; a4 -= 5; a5 -= 6; a6 -= 7; a7 -= 8;
+            a8 -= 9; a9 -= 10; a10 -= 11; a11 -= 12; a12 -= 13; a13 -= 14; a14 -= 15; a15 -= 16;
+            a16 -= 17; a17 -= 18; a18 -= 19; a19 -= 20; a20 -= 21; a21 -= 22; a22 -= 23; a23 -= 24;
+            a24 -= 25; a25 -= 26; a26 -= 27; a27 -= 28; a28 -= 29; a29 -= 30; a30 -= 31; a31 -= 32;
+        }
+
+        throw new Exception();
+    }
+}
diff --git a/src/tests/Exceptions/UnwindFpBleedTest/UnwindFpBleedTest.csproj b/src/tests/Exceptions/UnwindFpBleedTest/UnwindFpBleedTest.csproj
new file mode 100644 (file)
index 0000000..f4e80e7
--- /dev/null
@@ -0,0 +1,8 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="UnwindFpBleedTest.cs" />
+  </ItemGroup>
+</Project>
index 949a5d26976f1268244e1e18b4910adb1306c75b..73c5d7e38db5a9780f479a0bc11241925db6b54c 100644 (file)
         <ExcludeList Include="$(XunitTestBinBase)/JIT/jit64/opt/rngchk/RngchkStress3/*">
             <Issue>Needs Triage</Issue>
         </ExcludeList>
+        <ExcludeList Include="$(XunitTestBinBase)/Exceptions/UnwindFpBleedTest/UnwindFpBleedTest/*">
+          <Issue>Windows's unwinder in ARM64v8 queue doesn't contain FP unwind fix</Issue>
+        </ExcludeList>
     </ItemGroup>
 
     <!-- The following are x64 Unix failures on CoreCLR. -->
         <ExcludeList Include="$(XunitTestBinBase)/Interop/COM/Reflection/Reflection/**">
             <Issue>https://github.com/dotnet/runtime/issues/34371</Issue>
         </ExcludeList>
-        <ExcludeList Include="$(XunitTestBinBase)/Interop/COM/ComWrappers/**"> 
-            <Issue>Not supported on Mono</Issue> 
-        </ExcludeList>        
+        <ExcludeList Include="$(XunitTestBinBase)/Interop/COM/ComWrappers/**">
+            <Issue>Not supported on Mono</Issue>
+        </ExcludeList>
         <ExcludeList Include="$(XunitTestBinBase)/Interop/ICastable/Castable/**">
             <Issue>needs triage</Issue>
         </ExcludeList>