Skip to content

Commit

Permalink
Fix argument passing of structs with padding on x86 (#108867)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
BruceForstall authored Oct 15, 2024
1 parent a636e6d commit e1a14a8
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 4 deletions.
11 changes: 7 additions & 4 deletions src/coreclr/jit/codegenxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8239,12 +8239,15 @@ void CodeGen::genPutArgStkFieldList(GenTreePutArgStk* putArgStk)
unsigned pushSize = genTypeSize(genActualType(fieldType));
assert((pushSize % 4) == 0);
adjustment -= pushSize;

// If there is padding before this argument, zero it out.
assert((adjustment % TARGET_POINTER_SIZE) == 0);
while (adjustment != 0)
{
inst_IV(INS_push, 0);
currentOffset -= pushSize;
AddStackLevel(pushSize);
adjustment -= pushSize;
inst_IV(INS_push, 0); // Push TARGET_POINTER_SIZE bytes of zeros.
currentOffset -= TARGET_POINTER_SIZE;
AddStackLevel(TARGET_POINTER_SIZE);
adjustment -= TARGET_POINTER_SIZE;
}

m_pushStkArg = true;
Expand Down
32 changes: 32 additions & 0 deletions src/tests/JIT/Regression/JitBlue/Runtime_106140/Runtime_106140.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using Xunit;

public class Runtime_106140
{
public struct S1
{
public double F0;
public Vector256<int> F1;
public S1(bool f3) : this()
{
F1 = Vector256.Create(1,2,100,4,5,6,7,8);
}
}

[MethodImpl(MethodImplOptions.NoInlining)]
public static int t(S1 s)
{
return s.F1.GetElement(2);
}

[Fact]
public static void TestEntryPoint()
{
Assert.Equal(100, t(new S1(false)));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Optimize>True</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
</Project>

0 comments on commit e1a14a8

Please sign in to comment.