Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public class ArchitectureSpecificFieldLayoutTests
private ModuleDesc _testModuleARM;
private TestTypeSystemContext _contextARM64;
private ModuleDesc _testModuleARM64;
private TestTypeSystemContext _contextWasm32;
private ModuleDesc _testModuleWasm32;

public ArchitectureSpecificFieldLayoutTests()
{
Expand Down Expand Up @@ -60,6 +62,12 @@ public ArchitectureSpecificFieldLayoutTests()
_contextARM64.SetSystemModule(systemModuleARM64);

_testModuleARM64 = systemModuleARM64;

_contextWasm32 = new TestTypeSystemContext(TargetArchitecture.Wasm32, TargetOS.Browser);
var systemModuleWasm32 = _contextWasm32.CreateModuleForSimpleName("CoreTestAssembly");
_contextWasm32.SetSystemModule(systemModuleWasm32);

_testModuleWasm32 = systemModuleWasm32;
}

[Fact]
Expand Down Expand Up @@ -501,11 +509,13 @@ public void TestAlignmentBehavior_AutoAlignmentRules(string wrapperType, int[] a
[InlineData("StructStructByte_Int128StructAuto", "X86", 16, 32)]
[InlineData("StructStructByte_Int128StructAuto", "X64Linux", 16, 32)]
[InlineData("StructStructByte_Int128StructAuto", "X64Windows", 16, 32)]
[InlineData("StructStructByte_Int128StructAuto", "Wasm32", 16, 32)]
[InlineData("StructStructByte_UInt128StructAuto", "ARM64", 16, 32)]
[InlineData("StructStructByte_UInt128StructAuto", "ARM", 8, 24)]
[InlineData("StructStructByte_UInt128StructAuto", "X86", 16, 32)]
[InlineData("StructStructByte_UInt128StructAuto", "X64Linux", 16, 32)]
[InlineData("StructStructByte_UInt128StructAuto", "X64Windows", 16, 32)]
[InlineData("StructStructByte_UInt128StructAuto", "Wasm32", 16, 32)]
[InlineData("StructStructByte_Decimal32StructAuto", "ARM64", 4, 8)]
[InlineData("StructStructByte_Decimal32StructAuto", "ARM", 4, 8)]
[InlineData("StructStructByte_Decimal32StructAuto", "X86", 4, 8)]
Expand All @@ -521,6 +531,7 @@ public void TestAlignmentBehavior_AutoAlignmentRules(string wrapperType, int[] a
[InlineData("StructStructByte_Decimal128StructAuto", "X86", 16, 32)]
[InlineData("StructStructByte_Decimal128StructAuto", "X64Linux", 16, 32)]
[InlineData("StructStructByte_Decimal128StructAuto", "X64Windows", 16, 32)]
[InlineData("StructStructByte_Decimal128StructAuto", "Wasm32", 16, 32)]
// Variation of TestAlignmentBehavior_AutoAlignmentRules above that is able to deal with os specific behavior
public void TestAlignmentBehavior_AutoAlignmentRulesWithOSDependence(string wrapperType, string osArch, int alignment, int size)
{
Expand All @@ -545,6 +556,9 @@ public void TestAlignmentBehavior_AutoAlignmentRulesWithOSDependence(string wrap
case "X86":
testModule = _testModuleX86;
break;
case "Wasm32":
testModule = _testModuleWasm32;
break;
default:
throw new Exception();
}
Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/vm/methodtablebuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8683,7 +8683,8 @@ VOID MethodTableBuilder::HandleAutoLayout(MethodTable ** pByValueClassCache)

#ifdef FEATURE_64BIT_ALIGNMENT
if (GetHalfBakedClass()->IsAlign8Candidate()) {
minAlign = 8;
// Align8 is a minimum; keep any larger field alignment requirement.
minAlign = containsGCPointers ? 8 : max(8u, (unsigned)largestAlignmentRequirement);
}
else
#endif // FEATURE_64BIT_ALIGNMENT
Expand Down
37 changes: 35 additions & 2 deletions src/tests/readytorun/fieldlayout/fieldlayouttests.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
using System;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
using Xunit;
using TestLibrary;

public class Test
{
// This test uses the same set of types as the type system unittests use, and attempts to validate that the R2R usage of said types works well.
// This is done by touching the various types, and then relying on the verification logic in R2R images to detect failures.
[ActiveIssue("These tests are not supposed to be run with mono.", TestRuntimes.Mono)]
[ActiveIssue("https://github.com/dotnet/runtime/pull/131421", typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser), nameof(PlatformDetection.IsCoreCLR))]
[Fact]
public static void TestEntryPoint()
{
AutoStructWithInt128InDerivedClassTest.Test();
ContainsGCPointersFieldsTest.Test();
// ExplicitTest.Test(); // Explicit layout is known to not quite match the runtime, and if enabled this set of tests will fail.
SequentialTest.Test();
Expand All @@ -23,6 +23,39 @@ public static void TestEntryPoint()
}
}

// An auto layout struct with Int128 fields placed in a class whose base class has fields. The field
// offset compiled into R2R code must match the offset the runtime uses (observed via reflection).
class AutoStructWithInt128InDerivedClassTest
{
[StructLayout(LayoutKind.Auto)]
public struct Int128Pair
{
public Int128 First;
public Int128 Second;
}

public class Base
{
public char[] Chars = new char[1];
}

public sealed class Derived : Base
{
public Int128Pair Pair;
}

public static void Test()
{
Derived derived = new Derived();
derived.Pair.First = 0x1111;
derived.Pair.Second = -0x2222;

Int128Pair pair = (Int128Pair)typeof(Derived).GetField(nameof(Derived.Pair))!.GetValue(derived)!;
Assert.Equal((Int128)0x1111, pair.First);
Assert.Equal((Int128)(-0x2222), pair.Second);
}
}

class EnumAlignmentTest
{
static EnumAlignment.LongIntEnumStruct _fld1;
Expand Down
Loading