Skip to content

Commit 120e2f5

Browse files
Handle mis-sized structs in ARM/64 PUTARG_STK codegen (#69905)
* Handle mis-sized structs for PUTARG_STK on ARM/64 We will now generate a series of small loads as necessary to handle "remainderSize"s of 3, 5, 6 and 7. * Add tests * Re-enable tests for 60705
1 parent 9a185a7 commit 120e2f5

File tree

4 files changed

+216
-12
lines changed

4 files changed

+216
-12
lines changed

src/coreclr/jit/codegenarmarch.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,8 +1095,9 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode)
10951095

10961096
while (remainingSize > 0)
10971097
{
1098-
var_types type;
1098+
nextIndex = structOffset / TARGET_POINTER_SIZE;
10991099

1100+
var_types type;
11001101
if (remainingSize >= TARGET_POINTER_SIZE)
11011102
{
11021103
type = layout->GetGCPtrType(nextIndex);
@@ -1106,18 +1107,18 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode)
11061107
// the left over size is smaller than a pointer and thus can never be a GC type
11071108
assert(!layout->IsGCPtr(nextIndex));
11081109

1109-
if (remainingSize == 1)
1110+
if (remainingSize >= 4)
11101111
{
1111-
type = TYP_UBYTE;
1112+
type = TYP_INT;
11121113
}
1113-
else if (remainingSize == 2)
1114+
else if (remainingSize >= 2)
11141115
{
11151116
type = TYP_USHORT;
11161117
}
11171118
else
11181119
{
1119-
assert(remainingSize == 4);
1120-
type = TYP_UINT;
1120+
assert(remainingSize == 1);
1121+
type = TYP_UBYTE;
11211122
}
11221123
}
11231124

@@ -1146,7 +1147,6 @@ void CodeGen::genPutArgStk(GenTreePutArgStk* treeNode)
11461147
assert(argOffsetOut <= argOffsetMax); // We can't write beyond the outgoing arg area
11471148

11481149
structOffset += moveSize;
1149-
nextIndex++;
11501150
}
11511151
}
11521152
}

src/libraries/tests.proj

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,6 @@
9999
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Runtime.InteropServices\tests\LibraryImportGenerator.Tests\LibraryImportGenerator.Tests.csproj" />
100100
</ItemGroup>
101101

102-
<ItemGroup Condition="'$(TargetArchitecture)' == 'arm'">
103-
<!-- Issue: https://github.com/dotnet/runtime/issues/60705 -->
104-
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Runtime.InteropServices\tests\LibraryImportGenerator.UnitTests\LibraryImportGenerator.Unit.Tests.csproj" />
105-
</ItemGroup>
106-
107102
<ItemGroup Condition="'$(TargetOS)' == 'FreeBSD'">
108103
<!-- LibraryImportGenerator runtime tests build depends pulling down a pre-built nethost binary, which is not available for FreeBSD. -->
109104
<ProjectExclusions Include="$(MSBuildThisFileDirectory)System.Runtime.InteropServices\tests\LibraryImportGenerator.Tests\LibraryImportGenerator.Tests.csproj" />
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
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.InteropServices;
6+
using System.Runtime.CompilerServices;
7+
8+
public unsafe class MisSizedStructs
9+
{
10+
public const byte ByteValue = 0xC1;
11+
12+
public static int Main()
13+
{
14+
const int BytesSize = 256;
15+
var bytes = stackalloc byte[BytesSize];
16+
Unsafe.InitBlock(bytes, ByteValue, BytesSize);
17+
18+
if (ProblemWithStructWithThreeBytes(bytes))
19+
{
20+
return 101;
21+
}
22+
23+
if (ProblemWithStructWithFiveBytes(bytes))
24+
{
25+
return 102;
26+
}
27+
28+
if (ProblemWithStructWithSixBytes(bytes))
29+
{
30+
return 103;
31+
}
32+
33+
if (ProblemWithStructWithSevenBytes(bytes))
34+
{
35+
return 104;
36+
}
37+
38+
if (ProblemWithStructWithElevenBytes(bytes))
39+
{
40+
return 105;
41+
}
42+
43+
if (ProblemWithStructWithThirteenBytes(bytes))
44+
{
45+
return 106;
46+
}
47+
48+
if (ProblemWithStructWithFourteenBytes(bytes))
49+
{
50+
return 107;
51+
}
52+
53+
if (ProblemWithStructWithFifteenBytes(bytes))
54+
{
55+
return 108;
56+
}
57+
58+
if (ProblemWithStructWithNineteenBytes(bytes))
59+
{
60+
return 109;
61+
}
62+
63+
return 100;
64+
}
65+
66+
[MethodImpl(MethodImplOptions.NoInlining)]
67+
private static bool ProblemWithStructWithThreeBytes(byte* bytes)
68+
{
69+
return CallForStructWithThreeBytes(default, *(StructWithThreeBytes*)bytes) != ByteValue;
70+
}
71+
72+
[MethodImpl(MethodImplOptions.NoInlining)]
73+
private static bool ProblemWithStructWithFiveBytes(byte* bytes)
74+
{
75+
return CallForStructWithFiveBytes(default, *(StructWithFiveBytes*)bytes) != ByteValue;
76+
}
77+
78+
[MethodImpl(MethodImplOptions.NoInlining)]
79+
private static bool ProblemWithStructWithSixBytes(byte* bytes)
80+
{
81+
return CallForStructWithSixBytes(default, *(StructWithSixBytes*)bytes) != ByteValue;
82+
}
83+
84+
[MethodImpl(MethodImplOptions.NoInlining)]
85+
private static bool ProblemWithStructWithSevenBytes(byte* bytes)
86+
{
87+
return CallForStructWithSevenBytes(default, *(StructWithSevenBytes*)bytes) != ByteValue;
88+
}
89+
90+
[MethodImpl(MethodImplOptions.NoInlining)]
91+
private static bool ProblemWithStructWithElevenBytes(byte* bytes)
92+
{
93+
return CallForStructWithElevenBytes(default, *(StructWithElevenBytes*)bytes) != ByteValue;
94+
}
95+
96+
[MethodImpl(MethodImplOptions.NoInlining)]
97+
private static bool ProblemWithStructWithThirteenBytes(byte* bytes)
98+
{
99+
return CallForStructWithThirteenBytes(default, *(StructWithThirteenBytes*)bytes) != ByteValue;
100+
}
101+
102+
[MethodImpl(MethodImplOptions.NoInlining)]
103+
private static bool ProblemWithStructWithFourteenBytes(byte* bytes)
104+
{
105+
return CallForStructWithFourteenBytes(default, *(StructWithFourteenBytes*)bytes) != ByteValue;
106+
}
107+
108+
[MethodImpl(MethodImplOptions.NoInlining)]
109+
private static bool ProblemWithStructWithFifteenBytes(byte* bytes)
110+
{
111+
return CallForStructWithFifteenBytes(default, *(StructWithFifteenBytes*)bytes) != ByteValue;
112+
}
113+
114+
[MethodImpl(MethodImplOptions.NoInlining)]
115+
private static bool ProblemWithStructWithNineteenBytes(byte* bytes)
116+
{
117+
return CallForStructWithNineteenBytes(default, *(StructWithNineteenBytes*)bytes) != ByteValue;
118+
}
119+
120+
[MethodImpl(MethodImplOptions.NoInlining)]
121+
private static byte CallForStructWithThreeBytes(ForceStackUsage fs, StructWithThreeBytes value) => value.Bytes[2];
122+
123+
[MethodImpl(MethodImplOptions.NoInlining)]
124+
private static byte CallForStructWithFiveBytes(ForceStackUsage fs, StructWithFiveBytes value) => value.Bytes[4];
125+
126+
[MethodImpl(MethodImplOptions.NoInlining)]
127+
private static byte CallForStructWithSixBytes(ForceStackUsage fs, StructWithSixBytes value) => value.Bytes[5];
128+
129+
[MethodImpl(MethodImplOptions.NoInlining)]
130+
private static byte CallForStructWithSevenBytes(ForceStackUsage fs, StructWithSevenBytes value) => value.Bytes[6];
131+
132+
[MethodImpl(MethodImplOptions.NoInlining)]
133+
private static byte CallForStructWithElevenBytes(ForceStackUsage fs, StructWithElevenBytes value) => value.Bytes[10];
134+
135+
[MethodImpl(MethodImplOptions.NoInlining)]
136+
private static byte CallForStructWithThirteenBytes(ForceStackUsage fs, StructWithThirteenBytes value) => value.Bytes[12];
137+
138+
[MethodImpl(MethodImplOptions.NoInlining)]
139+
private static byte CallForStructWithFourteenBytes(ForceStackUsage fs, StructWithFourteenBytes value) => value.Bytes[13];
140+
141+
[MethodImpl(MethodImplOptions.NoInlining)]
142+
private static byte CallForStructWithFifteenBytes(ForceStackUsage fs, StructWithFifteenBytes value) => value.Bytes[14];
143+
144+
[MethodImpl(MethodImplOptions.NoInlining)]
145+
private static byte CallForStructWithNineteenBytes(ForceStackUsage fs, StructWithNineteenBytes value) => value.Bytes[18];
146+
147+
struct ForceStackUsage
148+
{
149+
public fixed byte Bytes[40];
150+
}
151+
152+
struct StructWithThreeBytes
153+
{
154+
public fixed byte Bytes[3];
155+
}
156+
157+
struct StructWithFiveBytes
158+
{
159+
public fixed byte Bytes[5];
160+
}
161+
162+
struct StructWithSixBytes
163+
{
164+
public fixed byte Bytes[6];
165+
}
166+
167+
struct StructWithSevenBytes
168+
{
169+
public fixed byte Bytes[7];
170+
}
171+
172+
struct StructWithElevenBytes
173+
{
174+
public fixed byte Bytes[11];
175+
}
176+
177+
struct StructWithThirteenBytes
178+
{
179+
public fixed byte Bytes[13];
180+
}
181+
182+
struct StructWithFourteenBytes
183+
{
184+
public fixed byte Bytes[14];
185+
}
186+
187+
struct StructWithFifteenBytes
188+
{
189+
public fixed byte Bytes[15];
190+
}
191+
192+
struct StructWithNineteenBytes
193+
{
194+
public fixed byte Bytes[19];
195+
}
196+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
5+
</PropertyGroup>
6+
<PropertyGroup>
7+
<DebugType>PdbOnly</DebugType>
8+
<Optimize>True</Optimize>
9+
</PropertyGroup>
10+
<ItemGroup>
11+
<Compile Include="$(MSBuildProjectName).cs" />
12+
</ItemGroup>
13+
</Project>

0 commit comments

Comments
 (0)