Skip to content

Commit e1a14a8

Browse files
Fix argument passing of structs with padding on x86 (#108867)
When passing a struct by value on x86, we copy its value to the stack. Sometimes this is done one field at a time, if the struct has been promoted. If there is padding between the fields (to create appropriate field alignment), then that padding needs to be zeroed. The bug is a case where there is padding between an earlier `double` field and a later, larger, SIMD field. We push 4-byte zeros but the code thinks it is pushing 8-byte zeros. The fix is simply to correctly calculate the number of zeros to push. Fixes #106140
1 parent a636e6d commit e1a14a8

File tree

3 files changed

+47
-4
lines changed

3 files changed

+47
-4
lines changed

src/coreclr/jit/codegenxarch.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8239,12 +8239,15 @@ void CodeGen::genPutArgStkFieldList(GenTreePutArgStk* putArgStk)
82398239
unsigned pushSize = genTypeSize(genActualType(fieldType));
82408240
assert((pushSize % 4) == 0);
82418241
adjustment -= pushSize;
8242+
8243+
// If there is padding before this argument, zero it out.
8244+
assert((adjustment % TARGET_POINTER_SIZE) == 0);
82428245
while (adjustment != 0)
82438246
{
8244-
inst_IV(INS_push, 0);
8245-
currentOffset -= pushSize;
8246-
AddStackLevel(pushSize);
8247-
adjustment -= pushSize;
8247+
inst_IV(INS_push, 0); // Push TARGET_POINTER_SIZE bytes of zeros.
8248+
currentOffset -= TARGET_POINTER_SIZE;
8249+
AddStackLevel(TARGET_POINTER_SIZE);
8250+
adjustment -= TARGET_POINTER_SIZE;
82488251
}
82498252

82508253
m_pushStkArg = true;
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Runtime.CompilerServices;
6+
using System.Runtime.Intrinsics;
7+
using Xunit;
8+
9+
public class Runtime_106140
10+
{
11+
public struct S1
12+
{
13+
public double F0;
14+
public Vector256<int> F1;
15+
public S1(bool f3) : this()
16+
{
17+
F1 = Vector256.Create(1,2,100,4,5,6,7,8);
18+
}
19+
}
20+
21+
[MethodImpl(MethodImplOptions.NoInlining)]
22+
public static int t(S1 s)
23+
{
24+
return s.F1.GetElement(2);
25+
}
26+
27+
[Fact]
28+
public static void TestEntryPoint()
29+
{
30+
Assert.Equal(100, t(new S1(false)));
31+
}
32+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<Optimize>True</Optimize>
4+
</PropertyGroup>
5+
<ItemGroup>
6+
<Compile Include="$(MSBuildProjectName).cs" />
7+
</ItemGroup>
8+
</Project>

0 commit comments

Comments
 (0)