Prevent LocalAddressVisitor from morphing x86 vararg params (#2157)
authormikedn <onemihaid@hotmail.com>
Tue, 28 Jan 2020 16:44:59 +0000 (18:44 +0200)
committerSergey Andreenko <seandree@microsoft.com>
Tue, 28 Jan 2020 16:44:59 +0000 (08:44 -0800)
fgMorphStackArgForVarArgs has no support for local address node nor LCL_FLD nodes.

src/coreclr/src/jit/lclmorph.cpp
src/coreclr/tests/src/JIT/Directed/arglist/vararg.cs
src/coreclr/tests/src/JIT/Directed/arglist/varargmanaged.cs

index 252a137..94ef5a6 100644 (file)
@@ -809,6 +809,15 @@ private:
             return;
         }
 
+#ifdef _TARGET_X86_
+        if (m_compiler->info.compIsVarArgs && varDsc->lvIsParam && !varDsc->lvIsRegArg)
+        {
+            // TODO-ADDR: For now we ignore all stack parameters of varargs methods,
+            // fgMorphStackArgForVarArgs does not handle LCL_VAR|FLD_ADDR nodes.
+            return;
+        }
+#endif
+
         GenTree* addr = val.Node();
 
         if (val.Offset() > UINT16_MAX)
@@ -891,6 +900,15 @@ private:
             return;
         }
 
+#ifdef _TARGET_X86_
+        if (m_compiler->info.compIsVarArgs && varDsc->lvIsParam && !varDsc->lvIsRegArg)
+        {
+            // TODO-ADDR: For now we ignore all stack parameters of varargs methods,
+            // fgMorphStackArgForVarArgs does not handle LCL_FLD nodes.
+            return;
+        }
+#endif
+
         ClassLayout*  structLayout = nullptr;
         FieldSeqNode* fieldSeq     = val.FieldSeq();
 
index cc2ccc4..8770c6e 100644 (file)
@@ -4422,6 +4422,26 @@ namespace NativeVarargTest
             return returnValue == (short)arg;
         }
 
+        // Tests that take the address of a parameter of a vararg method
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        static bool TestEchoFourDoubleStructManagedViaAddress()
+        {
+            FourDoubleStruct arg = new FourDoubleStruct();
+            arg.a = 1.0;
+            arg.b = 2.0;
+            arg.c = 3.0;
+            arg.d = 4.0;
+
+            FourDoubleStruct returnValue = ManagedNativeVarargTests.TestEchoFourDoubleStructManagedViaAddress(arg, __arglist(arg));
+            bool equal = arg.a == returnValue.a &&
+                         arg.b == returnValue.b &&
+                         arg.c == returnValue.c &&
+                         arg.d == returnValue.d;
+
+            return equal;
+        }
+
         ////////////////////////////////////////////////////////////////////////
         // Report Failure
         ////////////////////////////////////////////////////////////////////////
@@ -5043,6 +5063,9 @@ namespace NativeVarargTest
             success = ReportFailure(TestShortInByteOutNoVararg(7), "TestShortInByteOutNoVararg(7)", success, 108);
             success = ReportFailure(TestByteInShortOutNoVararg(8), "TestByteInShortOutNoVararg(8)", success, 109);
 
+            // Parameter address tests
+            success = ReportFailure(TestEchoFourDoubleStructManagedViaAddress(), "TestEchoFourDoubleStructManagedViaAddress()", success, 155);
+
             printf("\n", __arglist());
             printf("%d Tests run. %d Passed, %d Failed.\n", __arglist(m_testCount, m_passCount, m_failCount));
 
index d8b8ca5..c586d4e 100644 (file)
@@ -1315,5 +1315,22 @@ namespace NativeVarargTest
 
             return varArg;
         }
+
+        // Tests that take the address of a parameter of a vararg method
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        public static FourDoubleStruct TestEchoFourDoubleStructManagedViaAddress(FourDoubleStruct arg, __arglist)
+        {
+            ArgIterator it = new ArgIterator(__arglist);
+            var varArg = __refvalue(it.GetNextArg(), FourDoubleStruct);
+
+            return NewFourDoubleStructViaAddress(ref arg.a, ref arg.b, ref varArg.c, ref varArg.d);
+        }
+
+        [MethodImpl(MethodImplOptions.NoInlining)]
+        private static FourDoubleStruct NewFourDoubleStructViaAddress(ref double a, ref double b, ref double c, ref double d)
+        {
+            return new FourDoubleStruct { a = a, b = b, c = c, d = d };
+        }
     }
-}
\ No newline at end of file
+}