diff --git a/eng/pipelines/coreclr/ci.yml b/eng/pipelines/coreclr/ci.yml index d0d461e24c3264..117f645186fb94 100644 --- a/eng/pipelines/coreclr/ci.yml +++ b/eng/pipelines/coreclr/ci.yml @@ -147,7 +147,8 @@ jobs: jobParameters: testGroup: outerloop readyToRun: true - displayNameArgs: R2R + crossgen2: true + displayNameArgs: R2R_CG2 liveLibrariesBuildConfig: Release # diff --git a/src/coreclr/inc/readytorun.h b/src/coreclr/inc/readytorun.h index f35d80c37d1451..e29f75c4d6d221 100644 --- a/src/coreclr/inc/readytorun.h +++ b/src/coreclr/inc/readytorun.h @@ -15,10 +15,10 @@ #define READYTORUN_SIGNATURE 0x00525452 // 'RTR' // Keep these in sync with src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs -#define READYTORUN_MAJOR_VERSION 0x0005 -#define READYTORUN_MINOR_VERSION 0x0003 +#define READYTORUN_MAJOR_VERSION 0x0006 +#define READYTORUN_MINOR_VERSION 0x0001 -#define MINIMUM_READYTORUN_MAJOR_VERSION 0x003 +#define MINIMUM_READYTORUN_MAJOR_VERSION 0x006 // R2R Version 2.1 adds the InliningInfo section // R2R Version 2.2 adds the ProfileDataInfo section diff --git a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs index feacb0ba06d5d9..004800d2b2e853 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs @@ -14,8 +14,8 @@ internal struct ReadyToRunHeaderConstants { public const uint Signature = 0x00525452; // 'RTR' - public const ushort CurrentMajorVersion = 5; - public const ushort CurrentMinorVersion = 3; + public const ushort CurrentMajorVersion = 6; + public const ushort CurrentMinorVersion = 1; } #pragma warning disable 0169 diff --git a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs index f7372ba0d6edd9..ecba2ebce823b5 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs @@ -308,13 +308,11 @@ protected static ComputedInstanceFieldLayout ComputeExplicitFieldLayout(Metadata { // Instance slice size is the total size of instance not including the base type. // It is calculated as the field whose offset and size add to the greatest value. - LayoutInt offsetBias = !type.IsValueType ? new LayoutInt(type.Context.Target.PointerSize) : LayoutInt.Zero; - LayoutInt cumulativeInstanceFieldPos = - type.HasBaseType && !type.IsValueType ? type.BaseType.InstanceByteCount : LayoutInt.Zero; - LayoutInt instanceSize = cumulativeInstanceFieldPos; - cumulativeInstanceFieldPos -= offsetBias; + LayoutInt offsetBias = (!type.IsValueType ? type.Context.Target.LayoutPointerSize : LayoutInt.Zero); + LayoutInt cumulativeInstanceFieldPos = (type.HasBaseType && !type.IsValueType ? type.BaseType.InstanceByteCount : LayoutInt.Zero) - offsetBias; var layoutMetadata = type.GetClassLayout(); + LayoutInt instanceSize = cumulativeInstanceFieldPos + new LayoutInt(layoutMetadata.Size) + offsetBias; int packingSize = ComputePackingSize(type, layoutMetadata); LayoutInt largestAlignmentRequired = LayoutInt.One; @@ -349,6 +347,7 @@ protected static ComputedInstanceFieldLayout ComputeExplicitFieldLayout(Metadata ); if (needsToBeAligned) { + largestAlignmentRequired = LayoutInt.Max(largestAlignmentRequired, type.Context.Target.LayoutPointerSize); int offsetModulo = computedOffset.AsInt % type.Context.Target.PointerSize; if (offsetModulo != 0) { @@ -365,7 +364,11 @@ protected static ComputedInstanceFieldLayout ComputeExplicitFieldLayout(Metadata } SizeAndAlignment instanceByteSizeAndAlignment; - var instanceSizeAndAlignment = ComputeInstanceSize(type, instanceSize, largestAlignmentRequired, layoutMetadata.Size, out instanceByteSizeAndAlignment); + var instanceSizeAndAlignment = ComputeInstanceSize(type, + instanceSize, + largestAlignmentRequired, + layoutMetadata.Size, + out instanceByteSizeAndAlignment); ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout(); computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; @@ -375,7 +378,6 @@ protected static ComputedInstanceFieldLayout ComputeExplicitFieldLayout(Metadata computedLayout.Offsets = offsets; computedLayout.LayoutAbiStable = layoutAbiStable; - ExplicitLayoutValidator.Validate(type, computedLayout); return computedLayout; @@ -393,7 +395,7 @@ protected ComputedInstanceFieldLayout ComputeSequentialFieldLayout(MetadataType // For types inheriting from another type, field offsets continue on from where they left off // For reference types, we calculate field alignment as if the address after the method table pointer // has offset 0 (on 32-bit platforms, this location is guaranteed to be 8-aligned). - LayoutInt offsetBias = !type.IsValueType ? new LayoutInt(type.Context.Target.PointerSize) : LayoutInt.Zero; + LayoutInt offsetBias = (!type.IsValueType ? type.Context.Target.LayoutPointerSize : LayoutInt.Zero); LayoutInt cumulativeInstanceFieldPos = CalculateFieldBaseOffset(type, requiresAlign8: false, requiresAlignedBase: false) - offsetBias; var layoutMetadata = type.GetClassLayout(); @@ -422,7 +424,12 @@ protected ComputedInstanceFieldLayout ComputeSequentialFieldLayout(MetadataType } SizeAndAlignment instanceByteSizeAndAlignment; - var instanceSizeAndAlignment = ComputeInstanceSize(type, cumulativeInstanceFieldPos + offsetBias, largestAlignmentRequirement, layoutMetadata.Size, out instanceByteSizeAndAlignment); + var instanceSizeAndAlignment = ComputeInstanceSize( + type, + cumulativeInstanceFieldPos + offsetBias, + largestAlignmentRequirement, + layoutMetadata.Size, + out instanceByteSizeAndAlignment); ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout(); computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; @@ -546,7 +553,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, LayoutInt offsetBias = LayoutInt.Zero; if (!type.IsValueType && cumulativeInstanceFieldPos != LayoutInt.Zero && type.Context.Target.Architecture == TargetArchitecture.X86) { - offsetBias = new LayoutInt(type.Context.Target.PointerSize); + offsetBias = type.Context.Target.LayoutPointerSize; cumulativeInstanceFieldPos -= offsetBias; } @@ -704,7 +711,11 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, } SizeAndAlignment instanceByteSizeAndAlignment; - var instanceSizeAndAlignment = ComputeInstanceSize(type, cumulativeInstanceFieldPos + offsetBias, minAlign, 0/* specified field size unused */, out instanceByteSizeAndAlignment); + var instanceSizeAndAlignment = ComputeInstanceSize(type, + cumulativeInstanceFieldPos + offsetBias, + minAlign, + classLayoutSize: 0, + out instanceByteSizeAndAlignment); ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout(); computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; @@ -792,6 +803,10 @@ private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType, DefType metadataType = (DefType)fieldType; result.Size = metadataType.InstanceFieldSize; result.Alignment = metadataType.InstanceFieldAlignment; + if (!fieldType.IsPrimitive && !fieldType.IsEnum) + { + result.Alignment = LayoutInt.Min(metadataType.InstanceFieldAlignment, metadataType.Context.Target.GetObjectAlignment(metadataType.InstanceFieldAlignment)); + } layoutAbiStable = metadataType.LayoutAbiStable; } else @@ -840,25 +855,29 @@ private static SizeAndAlignment ComputeInstanceSize(MetadataType type, LayoutInt } TargetDetails target = type.Context.Target; + LayoutInt parentSize; + if (type.IsValueType || type.BaseType == null) + parentSize = new LayoutInt(0); + else + parentSize = type.BaseType.InstanceByteCountUnaligned; + LayoutInt specifiedInstanceSize = parentSize + new LayoutInt(classLayoutSize); - if (classLayoutSize != 0) + if (!instanceSize.IsIndeterminate && specifiedInstanceSize.AsInt >= instanceSize.AsInt) { - LayoutInt parentSize; - if (type.IsValueType) - parentSize = new LayoutInt(0); - else - parentSize = type.BaseType.InstanceByteCountUnaligned; - - LayoutInt specifiedInstanceSize = parentSize + new LayoutInt(classLayoutSize); - - instanceSize = LayoutInt.Max(specifiedInstanceSize, instanceSize); + instanceSize = specifiedInstanceSize; } - else + else if (type.IsValueType) { - if (type.IsValueType) + LayoutInt sizeAlignment; + if (type.IsEnum || type.IsPrimitive) + { + sizeAlignment = alignment; + } + else { - instanceSize = LayoutInt.AlignUp(instanceSize, alignment, target); + sizeAlignment = LayoutInt.Min(alignment, target.GetObjectAlignment(alignment)); } + instanceSize = LayoutInt.AlignUp(instanceSize, sizeAlignment, target); } if (type.IsValueType) diff --git a/src/coreclr/tools/Common/TypeSystem/Common/TargetDetails.cs b/src/coreclr/tools/Common/TypeSystem/Common/TargetDetails.cs index 21ea040857855e..c13280c148ccca 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/TargetDetails.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/TargetDetails.cs @@ -252,8 +252,15 @@ public LayoutInt GetWellKnownTypeSize(DefType type) /// public LayoutInt GetWellKnownTypeAlignment(DefType type) { - // Size == Alignment for all platforms. - return GetWellKnownTypeSize(type); + // Size == Alignment on 64-bit platforms, arm32 and Windows x86; on Unix x86, Alignment of 8-byte primitives is 4. + LayoutInt typeSize = GetWellKnownTypeSize(type); + if (Architecture == TargetArchitecture.X86 && OperatingSystem != TargetOS.Windows) + { + // Per https://github.com/dotnet/runtime/blob/b08a97afb8270511c39fe26d37038877bb63a09b/src/coreclr/vm/classlayoutinfo.cpp#L254 + // 8-byte types have alignment 4 on UNIX x86. + typeSize = LayoutInt.Min(typeSize, LayoutPointerSize); + } + return typeSize; } /// diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunMetadataFieldLayoutAlgorithm.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunMetadataFieldLayoutAlgorithm.cs index 1cc09466ee216e..236d6b0bafffe5 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunMetadataFieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunMetadataFieldLayoutAlgorithm.cs @@ -802,15 +802,46 @@ protected override ComputedInstanceFieldLayout ComputeInstanceFieldLayout(Metada { return ComputeExplicitFieldLayout(type, numInstanceFields); } - else - if (type.IsEnum || MarshalUtils.IsBlittableType(type) || IsManagedSequentialType(type)) + else if (LayoutContainsNoGCPointers(type)) { return ComputeSequentialFieldLayout(type, numInstanceFields); } - else + return ComputeAutoFieldLayout(type, numInstanceFields); + } + + private bool LayoutContainsNoGCPointers(TypeDesc type) + { + if (type.IsPrimitive || type.IsEnum || type.IsPointer || type.IsFunctionPointer) + { + return true; + } + MetadataType mdType = type as MetadataType; + if (mdType == null) + { + return false; + } + if (!mdType.IsValueType && mdType.HasBaseType && !LayoutContainsNoGCPointers(mdType.BaseType)) + { + return false; + } + if (!mdType.IsExplicitLayout && !mdType.IsSequentialLayout) + { + return false; + } + if (type.Category == TypeFlags.ValueType || + type.Category == TypeFlags.Class || + type.Category == TypeFlags.Nullable) { - return ComputeAutoFieldLayout(type, numInstanceFields); + foreach (FieldDesc field in type.GetFields()) + { + if (!field.IsStatic && (field.FieldType.Category == TypeFlags.Class || !LayoutContainsNoGCPointers(field.FieldType))) + { + return false; + } + } + return true; } + return false; } /// diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs index 0119522f0af4e4..4e296b1ab70207 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -2269,13 +2269,7 @@ private bool NeedsTypeLayoutCheck(TypeDesc type) private bool HasLayoutMetadata(TypeDesc type) { - if (type.IsValueType && (MarshalUtils.IsBlittableType(type) || ReadyToRunMetadataFieldLayoutAlgorithm.IsManagedSequentialType(type))) - { - // Sequential layout - return true; - } - - return false; + return type is MetadataType metadataType && (metadataType.IsSequentialLayout || metadataType.IsExplicitLayout); } /// diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/ArchitectureSpecificFieldLayoutTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/ArchitectureSpecificFieldLayoutTests.cs index 067486f858c168..414094ce45afeb 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/ArchitectureSpecificFieldLayoutTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/ArchitectureSpecificFieldLayoutTests.cs @@ -15,8 +15,10 @@ namespace TypeSystemTests { public class ArchitectureSpecificFieldLayoutTests { - TestTypeSystemContext _contextX86; - ModuleDesc _testModuleX86; + TestTypeSystemContext _contextX86Windows; + ModuleDesc _testModuleX86Windows; + TestTypeSystemContext _contextX86Unix; + ModuleDesc _testModuleX86Unix; TestTypeSystemContext _contextX64; ModuleDesc _testModuleX64; TestTypeSystemContext _contextARM; @@ -24,63 +26,77 @@ public class ArchitectureSpecificFieldLayoutTests public ArchitectureSpecificFieldLayoutTests() { - _contextX64 = new TestTypeSystemContext(TargetArchitecture.X64); + _contextX64 = new TestTypeSystemContext(TargetArchitecture.X64, TargetOS.Unknown); var systemModuleX64 = _contextX64.CreateModuleForSimpleName("CoreTestAssembly"); _contextX64.SetSystemModule(systemModuleX64); _testModuleX64 = systemModuleX64; - _contextARM = new TestTypeSystemContext(TargetArchitecture.ARM); + _contextARM = new TestTypeSystemContext(TargetArchitecture.ARM, TargetOS.Unknown); var systemModuleARM = _contextARM.CreateModuleForSimpleName("CoreTestAssembly"); _contextARM.SetSystemModule(systemModuleARM); _testModuleARM = systemModuleARM; - _contextX86 = new TestTypeSystemContext(TargetArchitecture.X86); - var systemModuleX86 = _contextX86.CreateModuleForSimpleName("CoreTestAssembly"); - _contextX86.SetSystemModule(systemModuleX86); + _contextX86Windows = new TestTypeSystemContext(TargetArchitecture.X86, TargetOS.Windows); + var systemModuleX86Windows = _contextX86Windows.CreateModuleForSimpleName("CoreTestAssembly"); + _contextX86Windows.SetSystemModule(systemModuleX86Windows); - _testModuleX86 = systemModuleX86; + _testModuleX86Windows = systemModuleX86Windows; + + _contextX86Unix = new TestTypeSystemContext(TargetArchitecture.X86, TargetOS.Linux); + var systemModuleX86Unix = _contextX86Unix.CreateModuleForSimpleName("CoreTestAssembly"); + _contextX86Unix.SetSystemModule(systemModuleX86Unix); + + _testModuleX86Unix = systemModuleX86Unix; } [Fact] public void TestInstanceLayoutDoubleBool() { MetadataType tX64 = _testModuleX64.GetType("Sequential", "ClassDoubleBool"); - MetadataType tX86 = _testModuleX86.GetType("Sequential", "ClassDoubleBool"); + MetadataType tX86Windows = _testModuleX86Windows.GetType("Sequential", "ClassDoubleBool"); + MetadataType tX86Unix = _testModuleX86Unix.GetType("Sequential", "ClassDoubleBool"); MetadataType tARM = _testModuleARM.GetType("Sequential", "ClassDoubleBool"); Assert.Equal(0x8, tX64.InstanceByteAlignment.AsInt); Assert.Equal(0x8, tARM.InstanceByteAlignment.AsInt); - Assert.Equal(0x4, tX86.InstanceByteAlignment.AsInt); + Assert.Equal(0x4, tX86Windows.InstanceByteAlignment.AsInt); + Assert.Equal(0x4, tX86Unix.InstanceByteAlignment.AsInt); Assert.Equal(0x11, tX64.InstanceByteCountUnaligned.AsInt); Assert.Equal(0xD, tARM.InstanceByteCountUnaligned.AsInt); - Assert.Equal(0xD, tX86.InstanceByteCountUnaligned.AsInt); + Assert.Equal(0xD, tX86Windows.InstanceByteCountUnaligned.AsInt); + Assert.Equal(0xD, tX86Unix.InstanceByteCountUnaligned.AsInt); Assert.Equal(0x18, tX64.InstanceByteCount.AsInt); Assert.Equal(0x10, tARM.InstanceByteCount.AsInt); - Assert.Equal(0x10, tX86.InstanceByteCount.AsInt); + Assert.Equal(0x10, tX86Windows.InstanceByteCount.AsInt); + Assert.Equal(0x10, tX86Unix.InstanceByteCount.AsInt); } [Fact] public void TestInstanceLayoutBoolDoubleBool() { MetadataType tX64 = _testModuleX64.GetType("Sequential", "ClassBoolDoubleBool"); - MetadataType tX86 = _testModuleX86.GetType("Sequential", "ClassBoolDoubleBool"); + MetadataType tX86Windows = _testModuleX86Windows.GetType("Sequential", "ClassBoolDoubleBool"); + MetadataType tX86Unix = _testModuleX86Unix.GetType("Sequential", "ClassBoolDoubleBool"); MetadataType tARM = _testModuleARM.GetType("Sequential", "ClassBoolDoubleBool"); Assert.Equal(0x8, tX64.InstanceByteAlignment.AsInt); Assert.Equal(0x8, tARM.InstanceByteAlignment.AsInt); - Assert.Equal(0x4, tX86.InstanceByteAlignment.AsInt); + Assert.Equal(0x4, tX86Windows.InstanceByteAlignment.AsInt); + Assert.Equal(0x4, tX86Unix.InstanceByteAlignment.AsInt); Assert.Equal(0x19, tX64.InstanceByteCountUnaligned.AsInt); Assert.Equal(0x15, tARM.InstanceByteCountUnaligned.AsInt); - Assert.Equal(0x15, tX86.InstanceByteCountUnaligned.AsInt); + Assert.Equal(0x15, tX86Windows.InstanceByteCountUnaligned.AsInt); + Assert.Equal(0x11, tX86Unix.InstanceByteCountUnaligned.AsInt); Assert.Equal(0x20, tX64.InstanceByteCount.AsInt); Assert.Equal(0x18, tARM.InstanceByteCount.AsInt); - Assert.Equal(0x18, tX86.InstanceByteCount.AsInt); + Assert.Equal(0x18, tX86Windows.InstanceByteCount.AsInt); + Assert.Equal(0x14, tX86Unix.InstanceByteCount.AsInt); } [Fact] @@ -90,51 +106,63 @@ public void TestAlignmentBehavior_LongIntEnumStruct() string _type = "LongIntEnumStruct"; MetadataType tX64 = _testModuleX64.GetType(_namespace, _type); - MetadataType tX86 = _testModuleX86.GetType(_namespace, _type); + MetadataType tX86Windows = _testModuleX86Windows.GetType(_namespace, _type); + MetadataType tX86Unix = _testModuleX86Unix.GetType(_namespace, _type); MetadataType tARM = _testModuleARM.GetType(_namespace, _type); Assert.Equal(0x8, tX64.InstanceByteAlignment.AsInt); Assert.Equal(0x8, tARM.InstanceByteAlignment.AsInt); - Assert.Equal(0x4, tX86.InstanceByteAlignment.AsInt); + Assert.Equal(0x4, tX86Windows.InstanceByteAlignment.AsInt); + Assert.Equal(0x4, tX86Unix.InstanceByteAlignment.AsInt); Assert.Equal(0x20, tX64.InstanceByteCountUnaligned.AsInt); Assert.Equal(0x20, tARM.InstanceByteCountUnaligned.AsInt); - Assert.Equal(0x20, tX86.InstanceByteCountUnaligned.AsInt); + Assert.Equal(0x1C, tX86Windows.InstanceByteCountUnaligned.AsInt); + Assert.Equal(0x18, tX86Unix.InstanceByteCountUnaligned.AsInt); Assert.Equal(0x20, tX64.InstanceByteCount.AsInt); Assert.Equal(0x20, tARM.InstanceByteCount.AsInt); - Assert.Equal(0x20, tX86.InstanceByteCount.AsInt); + Assert.Equal(0x1C, tX86Windows.InstanceByteCount.AsInt); + Assert.Equal(0x18, tX86Unix.InstanceByteCount.AsInt); Assert.Equal(0x8, tX64.InstanceFieldAlignment.AsInt); Assert.Equal(0x8, tARM.InstanceFieldAlignment.AsInt); - Assert.Equal(0x8, tX86.InstanceFieldAlignment.AsInt); + Assert.Equal(0x8, tX86Windows.InstanceFieldAlignment.AsInt); + Assert.Equal(0x4, tX86Unix.InstanceFieldAlignment.AsInt); Assert.Equal(0x20, tX64.InstanceFieldSize.AsInt); Assert.Equal(0x20, tARM.InstanceFieldSize.AsInt); - Assert.Equal(0x20, tX86.InstanceFieldSize.AsInt); + Assert.Equal(0x1C, tX86Windows.InstanceFieldSize.AsInt); + Assert.Equal(0x18, tX86Unix.InstanceFieldSize.AsInt); Assert.Equal(0x0, tX64.GetField("_1").Offset.AsInt); Assert.Equal(0x0, tARM.GetField("_1").Offset.AsInt); - Assert.Equal(0x0, tX86.GetField("_1").Offset.AsInt); + Assert.Equal(0x0, tX86Windows.GetField("_1").Offset.AsInt); + Assert.Equal(0x0, tX86Unix.GetField("_1").Offset.AsInt); Assert.Equal(0x8, tX64.GetField("_2").Offset.AsInt); Assert.Equal(0x8, tARM.GetField("_2").Offset.AsInt); - Assert.Equal(0x8, tX86.GetField("_2").Offset.AsInt); + Assert.Equal(0x8, tX86Windows.GetField("_2").Offset.AsInt); + Assert.Equal(0x8, tX86Unix.GetField("_2").Offset.AsInt); Assert.Equal(0x10, tX64.GetField("_3").Offset.AsInt); Assert.Equal(0x10, tARM.GetField("_3").Offset.AsInt); - Assert.Equal(0x10, tX86.GetField("_3").Offset.AsInt); + Assert.Equal(0x10, tX86Windows.GetField("_3").Offset.AsInt); + Assert.Equal(0x0C, tX86Unix.GetField("_3").Offset.AsInt); Assert.Equal(0x18, tX64.GetField("_4").Offset.AsInt); Assert.Equal(0x18, tARM.GetField("_4").Offset.AsInt); - Assert.Equal(0x18, tX86.GetField("_4").Offset.AsInt); + Assert.Equal(0x18, tX86Windows.GetField("_4").Offset.AsInt); + Assert.Equal(0x14, tX86Unix.GetField("_4").Offset.AsInt); MetadataType tX64FieldStruct = _testModuleX64.GetType(_namespace, _type + "FieldStruct"); - MetadataType tX86FieldStruct = _testModuleX86.GetType(_namespace, _type + "FieldStruct"); + MetadataType tX86FieldStructWindows = _testModuleX86Windows.GetType(_namespace, _type + "FieldStruct"); + MetadataType tX86FieldStructUnix = _testModuleX86Unix.GetType(_namespace, _type + "FieldStruct"); MetadataType tARMFieldStruct = _testModuleARM.GetType(_namespace, _type + "FieldStruct"); Assert.Equal(0x8, tX64FieldStruct.GetField("_struct").Offset.AsInt); - Assert.Equal(0x8, tX86FieldStruct.GetField("_struct").Offset.AsInt); + Assert.Equal(0x4, tX86FieldStructWindows.GetField("_struct").Offset.AsInt); + Assert.Equal(0x4, tX86FieldStructUnix.GetField("_struct").Offset.AsInt); Assert.Equal(0x8, tARMFieldStruct.GetField("_struct").Offset.AsInt); } @@ -145,51 +173,63 @@ public void TestAlignmentBehavior_IntShortEnumStruct() string _type = "IntShortEnumStruct"; MetadataType tX64 = _testModuleX64.GetType(_namespace, _type); - MetadataType tX86 = _testModuleX86.GetType(_namespace, _type); + MetadataType tX86Windows = _testModuleX86Windows.GetType(_namespace, _type); + MetadataType tX86Unix = _testModuleX86Unix.GetType(_namespace, _type); MetadataType tARM = _testModuleARM.GetType(_namespace, _type); Assert.Equal(0x8, tX64.InstanceByteAlignment.AsInt); Assert.Equal(0x4, tARM.InstanceByteAlignment.AsInt); - Assert.Equal(0x4, tX86.InstanceByteAlignment.AsInt); + Assert.Equal(0x4, tX86Windows.InstanceByteAlignment.AsInt); + Assert.Equal(0x4, tX86Unix.InstanceByteAlignment.AsInt); Assert.Equal(0x10, tX64.InstanceByteCountUnaligned.AsInt); Assert.Equal(0x10, tARM.InstanceByteCountUnaligned.AsInt); - Assert.Equal(0x10, tX86.InstanceByteCountUnaligned.AsInt); + Assert.Equal(0x10, tX86Windows.InstanceByteCountUnaligned.AsInt); + Assert.Equal(0x10, tX86Unix.InstanceByteCountUnaligned.AsInt); Assert.Equal(0x10, tX64.InstanceByteCount.AsInt); Assert.Equal(0x10, tARM.InstanceByteCount.AsInt); - Assert.Equal(0x10, tX86.InstanceByteCount.AsInt); + Assert.Equal(0x10, tX86Windows.InstanceByteCount.AsInt); + Assert.Equal(0x10, tX86Unix.InstanceByteCount.AsInt); Assert.Equal(0x4, tX64.InstanceFieldAlignment.AsInt); Assert.Equal(0x4, tARM.InstanceFieldAlignment.AsInt); - Assert.Equal(0x4, tX86.InstanceFieldAlignment.AsInt); + Assert.Equal(0x4, tX86Windows.InstanceFieldAlignment.AsInt); + Assert.Equal(0x4, tX86Unix.InstanceFieldAlignment.AsInt); Assert.Equal(0x10, tX64.InstanceFieldSize.AsInt); Assert.Equal(0x10, tARM.InstanceFieldSize.AsInt); - Assert.Equal(0x10, tX86.InstanceFieldSize.AsInt); + Assert.Equal(0x10, tX86Windows.InstanceFieldSize.AsInt); + Assert.Equal(0x10, tX86Unix.InstanceFieldSize.AsInt); Assert.Equal(0x0, tX64.GetField("_1").Offset.AsInt); Assert.Equal(0x0, tARM.GetField("_1").Offset.AsInt); - Assert.Equal(0x0, tX86.GetField("_1").Offset.AsInt); + Assert.Equal(0x0, tX86Windows.GetField("_1").Offset.AsInt); + Assert.Equal(0x0, tX86Unix.GetField("_1").Offset.AsInt); Assert.Equal(0x4, tX64.GetField("_2").Offset.AsInt); Assert.Equal(0x4, tARM.GetField("_2").Offset.AsInt); - Assert.Equal(0x4, tX86.GetField("_2").Offset.AsInt); + Assert.Equal(0x4, tX86Windows.GetField("_2").Offset.AsInt); + Assert.Equal(0x4, tX86Unix.GetField("_2").Offset.AsInt); Assert.Equal(0x8, tX64.GetField("_3").Offset.AsInt); Assert.Equal(0x8, tARM.GetField("_3").Offset.AsInt); - Assert.Equal(0x8, tX86.GetField("_3").Offset.AsInt); + Assert.Equal(0x8, tX86Windows.GetField("_3").Offset.AsInt); + Assert.Equal(0x8, tX86Unix.GetField("_3").Offset.AsInt); Assert.Equal(0xC, tX64.GetField("_4").Offset.AsInt); Assert.Equal(0xC, tARM.GetField("_4").Offset.AsInt); - Assert.Equal(0xC, tX86.GetField("_4").Offset.AsInt); + Assert.Equal(0xC, tX86Windows.GetField("_4").Offset.AsInt); + Assert.Equal(0xC, tX86Unix.GetField("_4").Offset.AsInt); MetadataType tX64FieldStruct = _testModuleX64.GetType(_namespace, _type + "FieldStruct"); - MetadataType tX86FieldStruct = _testModuleX86.GetType(_namespace, _type + "FieldStruct"); + MetadataType tX86FieldStructWindows = _testModuleX86Windows.GetType(_namespace, _type + "FieldStruct"); + MetadataType tX86FieldStructUnix = _testModuleX86Unix.GetType(_namespace, _type + "FieldStruct"); MetadataType tARMFieldStruct = _testModuleARM.GetType(_namespace, _type + "FieldStruct"); Assert.Equal(0x4, tX64FieldStruct.GetField("_struct").Offset.AsInt); - Assert.Equal(0x4, tX86FieldStruct.GetField("_struct").Offset.AsInt); + Assert.Equal(0x4, tX86FieldStructWindows.GetField("_struct").Offset.AsInt); + Assert.Equal(0x4, tX86FieldStructUnix.GetField("_struct").Offset.AsInt); Assert.Equal(0x4, tARMFieldStruct.GetField("_struct").Offset.AsInt); } @@ -201,51 +241,63 @@ public void TestAlignmentBehavior_ShortByteEnumStruct() string _type = "ShortByteEnumStruct"; MetadataType tX64 = _testModuleX64.GetType(_namespace, _type); - MetadataType tX86 = _testModuleX86.GetType(_namespace, _type); + MetadataType tX86Windows = _testModuleX86Windows.GetType(_namespace, _type); + MetadataType tX86Unix = _testModuleX86Unix.GetType(_namespace, _type); MetadataType tARM = _testModuleARM.GetType(_namespace, _type); Assert.Equal(0x8, tX64.InstanceByteAlignment.AsInt); Assert.Equal(0x4, tARM.InstanceByteAlignment.AsInt); - Assert.Equal(0x4, tX86.InstanceByteAlignment.AsInt); + Assert.Equal(0x4, tX86Windows.InstanceByteAlignment.AsInt); + Assert.Equal(0x4, tX86Unix.InstanceByteAlignment.AsInt); Assert.Equal(0x8, tX64.InstanceByteCountUnaligned.AsInt); Assert.Equal(0x8, tARM.InstanceByteCountUnaligned.AsInt); - Assert.Equal(0x8, tX86.InstanceByteCountUnaligned.AsInt); + Assert.Equal(0x8, tX86Windows.InstanceByteCountUnaligned.AsInt); + Assert.Equal(0x8, tX86Unix.InstanceByteCountUnaligned.AsInt); Assert.Equal(0x8, tX64.InstanceByteCount.AsInt); Assert.Equal(0x8, tARM.InstanceByteCount.AsInt); - Assert.Equal(0x8, tX86.InstanceByteCount.AsInt); + Assert.Equal(0x8, tX86Windows.InstanceByteCount.AsInt); + Assert.Equal(0x8, tX86Unix.InstanceByteCount.AsInt); Assert.Equal(0x2, tX64.InstanceFieldAlignment.AsInt); Assert.Equal(0x2, tARM.InstanceFieldAlignment.AsInt); - Assert.Equal(0x2, tX86.InstanceFieldAlignment.AsInt); + Assert.Equal(0x2, tX86Windows.InstanceFieldAlignment.AsInt); + Assert.Equal(0x2, tX86Unix.InstanceFieldAlignment.AsInt); Assert.Equal(0x8, tX64.InstanceFieldSize.AsInt); Assert.Equal(0x8, tARM.InstanceFieldSize.AsInt); - Assert.Equal(0x8, tX86.InstanceFieldSize.AsInt); + Assert.Equal(0x8, tX86Windows.InstanceFieldSize.AsInt); + Assert.Equal(0x8, tX86Unix.InstanceFieldSize.AsInt); Assert.Equal(0x0, tX64.GetField("_1").Offset.AsInt); Assert.Equal(0x0, tARM.GetField("_1").Offset.AsInt); - Assert.Equal(0x0, tX86.GetField("_1").Offset.AsInt); + Assert.Equal(0x0, tX86Windows.GetField("_1").Offset.AsInt); + Assert.Equal(0x0, tX86Unix.GetField("_1").Offset.AsInt); Assert.Equal(0x2, tX64.GetField("_2").Offset.AsInt); Assert.Equal(0x2, tARM.GetField("_2").Offset.AsInt); - Assert.Equal(0x2, tX86.GetField("_2").Offset.AsInt); + Assert.Equal(0x2, tX86Windows.GetField("_2").Offset.AsInt); + Assert.Equal(0x2, tX86Unix.GetField("_2").Offset.AsInt); Assert.Equal(0x4, tX64.GetField("_3").Offset.AsInt); Assert.Equal(0x4, tARM.GetField("_3").Offset.AsInt); - Assert.Equal(0x4, tX86.GetField("_3").Offset.AsInt); + Assert.Equal(0x4, tX86Windows.GetField("_3").Offset.AsInt); + Assert.Equal(0x4, tX86Unix.GetField("_3").Offset.AsInt); Assert.Equal(0x6, tX64.GetField("_4").Offset.AsInt); Assert.Equal(0x6, tARM.GetField("_4").Offset.AsInt); - Assert.Equal(0x6, tX86.GetField("_4").Offset.AsInt); + Assert.Equal(0x6, tX86Windows.GetField("_4").Offset.AsInt); + Assert.Equal(0x6, tX86Unix.GetField("_4").Offset.AsInt); MetadataType tX64FieldStruct = _testModuleX64.GetType(_namespace, _type + "FieldStruct"); - MetadataType tX86FieldStruct = _testModuleX86.GetType(_namespace, _type + "FieldStruct"); + MetadataType tX86FieldStructWindows = _testModuleX86Windows.GetType(_namespace, _type + "FieldStruct"); + MetadataType tX86FieldStructUnix = _testModuleX86Unix.GetType(_namespace, _type + "FieldStruct"); MetadataType tARMFieldStruct = _testModuleARM.GetType(_namespace, _type + "FieldStruct"); Assert.Equal(0x2, tX64FieldStruct.GetField("_struct").Offset.AsInt); - Assert.Equal(0x2, tX86FieldStruct.GetField("_struct").Offset.AsInt); + Assert.Equal(0x2, tX86FieldStructWindows.GetField("_struct").Offset.AsInt); + Assert.Equal(0x2, tX86FieldStructUnix.GetField("_struct").Offset.AsInt); Assert.Equal(0x2, tARMFieldStruct.GetField("_struct").Offset.AsInt); } @@ -256,51 +308,63 @@ public void TestAlignmentBehavior_LongIntEnumStructAuto() string _type = "LongIntEnumStructAuto"; MetadataType tX64 = _testModuleX64.GetType(_namespace, _type); - MetadataType tX86 = _testModuleX86.GetType(_namespace, _type); + MetadataType tX86Windows = _testModuleX86Windows.GetType(_namespace, _type); + MetadataType tX86Unix = _testModuleX86Unix.GetType(_namespace, _type); MetadataType tARM = _testModuleARM.GetType(_namespace, _type); Assert.Equal(0x8, tX64.InstanceByteAlignment.AsInt); Assert.Equal(0x8, tARM.InstanceByteAlignment.AsInt); - Assert.Equal(0x4, tX86.InstanceByteAlignment.AsInt); + Assert.Equal(0x4, tX86Windows.InstanceByteAlignment.AsInt); + Assert.Equal(0x4, tX86Unix.InstanceByteAlignment.AsInt); Assert.Equal(0x18, tX64.InstanceByteCountUnaligned.AsInt); Assert.Equal(0x18, tARM.InstanceByteCountUnaligned.AsInt); - Assert.Equal(0x18, tX86.InstanceByteCountUnaligned.AsInt); + Assert.Equal(0x18, tX86Windows.InstanceByteCountUnaligned.AsInt); + Assert.Equal(0x18, tX86Unix.InstanceByteCountUnaligned.AsInt); Assert.Equal(0x18, tX64.InstanceByteCount.AsInt); Assert.Equal(0x18, tARM.InstanceByteCount.AsInt); - Assert.Equal(0x18, tX86.InstanceByteCount.AsInt); + Assert.Equal(0x18, tX86Windows.InstanceByteCount.AsInt); + Assert.Equal(0x18, tX86Unix.InstanceByteCount.AsInt); Assert.Equal(0x8, tX64.InstanceFieldAlignment.AsInt); Assert.Equal(0x8, tARM.InstanceFieldAlignment.AsInt); - Assert.Equal(0x4, tX86.InstanceFieldAlignment.AsInt); + Assert.Equal(0x4, tX86Windows.InstanceFieldAlignment.AsInt); + Assert.Equal(0x4, tX86Unix.InstanceFieldAlignment.AsInt); Assert.Equal(0x18, tX64.InstanceFieldSize.AsInt); Assert.Equal(0x18, tARM.InstanceFieldSize.AsInt); - Assert.Equal(0x18, tX86.InstanceFieldSize.AsInt); + Assert.Equal(0x18, tX86Windows.InstanceFieldSize.AsInt); + Assert.Equal(0x18, tX86Unix.InstanceFieldSize.AsInt); Assert.Equal(0x0, tX64.GetField("_1").Offset.AsInt); Assert.Equal(0x0, tARM.GetField("_1").Offset.AsInt); - Assert.Equal(0x0, tX86.GetField("_1").Offset.AsInt); + Assert.Equal(0x0, tX86Windows.GetField("_1").Offset.AsInt); + Assert.Equal(0x0, tX86Unix.GetField("_1").Offset.AsInt); Assert.Equal(0x10, tX64.GetField("_2").Offset.AsInt); Assert.Equal(0x10, tARM.GetField("_2").Offset.AsInt); - Assert.Equal(0x10, tX86.GetField("_2").Offset.AsInt); + Assert.Equal(0x10, tX86Windows.GetField("_2").Offset.AsInt); + Assert.Equal(0x10, tX86Unix.GetField("_2").Offset.AsInt); Assert.Equal(0x8, tX64.GetField("_3").Offset.AsInt); Assert.Equal(0x8, tARM.GetField("_3").Offset.AsInt); - Assert.Equal(0x8, tX86.GetField("_3").Offset.AsInt); + Assert.Equal(0x8, tX86Windows.GetField("_3").Offset.AsInt); + Assert.Equal(0x8, tX86Unix.GetField("_3").Offset.AsInt); Assert.Equal(0x14, tX64.GetField("_4").Offset.AsInt); Assert.Equal(0x14, tARM.GetField("_4").Offset.AsInt); - Assert.Equal(0x14, tX86.GetField("_4").Offset.AsInt); + Assert.Equal(0x14, tX86Windows.GetField("_4").Offset.AsInt); + Assert.Equal(0x14, tX86Unix.GetField("_4").Offset.AsInt); MetadataType tX64FieldStruct = _testModuleX64.GetType(_namespace, _type + "FieldStruct"); - MetadataType tX86FieldStruct = _testModuleX86.GetType(_namespace, _type + "FieldStruct"); + MetadataType tX86WindowsFieldStruct = _testModuleX86Windows.GetType(_namespace, _type + "FieldStruct"); + MetadataType tX86UnixFieldStruct = _testModuleX86Unix.GetType(_namespace, _type + "FieldStruct"); MetadataType tARMFieldStruct = _testModuleARM.GetType(_namespace, _type + "FieldStruct"); Assert.Equal(0x8, tX64FieldStruct.GetField("_struct").Offset.AsInt); - Assert.Equal(0x4, tX86FieldStruct.GetField("_struct").Offset.AsInt); + Assert.Equal(0x4, tX86WindowsFieldStruct.GetField("_struct").Offset.AsInt); + Assert.Equal(0x4, tX86UnixFieldStruct.GetField("_struct").Offset.AsInt); Assert.Equal(0x8, tARMFieldStruct.GetField("_struct").Offset.AsInt); } @@ -311,51 +375,63 @@ public void TestAlignmentBehavior_IntShortEnumStructAuto() string _type = "IntShortEnumStructAuto"; MetadataType tX64 = _testModuleX64.GetType(_namespace, _type); - MetadataType tX86 = _testModuleX86.GetType(_namespace, _type); + MetadataType tX86Windows = _testModuleX86Windows.GetType(_namespace, _type); + MetadataType tX86Unix = _testModuleX86Unix.GetType(_namespace, _type); MetadataType tARM = _testModuleARM.GetType(_namespace, _type); Assert.Equal(0x8, tX64.InstanceByteAlignment.AsInt); Assert.Equal(0x4, tARM.InstanceByteAlignment.AsInt); - Assert.Equal(0x4, tX86.InstanceByteAlignment.AsInt); + Assert.Equal(0x4, tX86Windows.InstanceByteAlignment.AsInt); + Assert.Equal(0x4, tX86Unix.InstanceByteAlignment.AsInt); Assert.Equal(0x10, tX64.InstanceByteCountUnaligned.AsInt); Assert.Equal(0xC, tARM.InstanceByteCountUnaligned.AsInt); - Assert.Equal(0xC, tX86.InstanceByteCountUnaligned.AsInt); + Assert.Equal(0xC, tX86Windows.InstanceByteCountUnaligned.AsInt); + Assert.Equal(0xC, tX86Unix.InstanceByteCountUnaligned.AsInt); Assert.Equal(0x10, tX64.InstanceByteCount.AsInt); Assert.Equal(0xC, tARM.InstanceByteCount.AsInt); - Assert.Equal(0xC, tX86.InstanceByteCount.AsInt); + Assert.Equal(0xC, tX86Windows.InstanceByteCount.AsInt); + Assert.Equal(0xC, tX86Unix.InstanceByteCount.AsInt); Assert.Equal(0x8, tX64.InstanceFieldAlignment.AsInt); Assert.Equal(0x4, tARM.InstanceFieldAlignment.AsInt); - Assert.Equal(0x4, tX86.InstanceFieldAlignment.AsInt); + Assert.Equal(0x4, tX86Windows.InstanceFieldAlignment.AsInt); + Assert.Equal(0x4, tX86Unix.InstanceFieldAlignment.AsInt); Assert.Equal(0x10, tX64.InstanceFieldSize.AsInt); Assert.Equal(0xC, tARM.InstanceFieldSize.AsInt); - Assert.Equal(0xC, tX86.InstanceFieldSize.AsInt); + Assert.Equal(0xC, tX86Windows.InstanceFieldSize.AsInt); + Assert.Equal(0xC, tX86Unix.InstanceFieldSize.AsInt); Assert.Equal(0x0, tX64.GetField("_1").Offset.AsInt); Assert.Equal(0x0, tARM.GetField("_1").Offset.AsInt); - Assert.Equal(0x0, tX86.GetField("_1").Offset.AsInt); + Assert.Equal(0x0, tX86Windows.GetField("_1").Offset.AsInt); + Assert.Equal(0x0, tX86Unix.GetField("_1").Offset.AsInt); Assert.Equal(0x8, tX64.GetField("_2").Offset.AsInt); Assert.Equal(0x8, tARM.GetField("_2").Offset.AsInt); - Assert.Equal(0x8, tX86.GetField("_2").Offset.AsInt); + Assert.Equal(0x8, tX86Windows.GetField("_2").Offset.AsInt); + Assert.Equal(0x8, tX86Unix.GetField("_2").Offset.AsInt); Assert.Equal(0x4, tX64.GetField("_3").Offset.AsInt); Assert.Equal(0x4, tARM.GetField("_3").Offset.AsInt); - Assert.Equal(0x4, tX86.GetField("_3").Offset.AsInt); + Assert.Equal(0x4, tX86Windows.GetField("_3").Offset.AsInt); + Assert.Equal(0x4, tX86Unix.GetField("_3").Offset.AsInt); Assert.Equal(0xA, tX64.GetField("_4").Offset.AsInt); Assert.Equal(0xA, tARM.GetField("_4").Offset.AsInt); - Assert.Equal(0xA, tX86.GetField("_4").Offset.AsInt); + Assert.Equal(0xA, tX86Windows.GetField("_4").Offset.AsInt); + Assert.Equal(0xA, tX86Unix.GetField("_4").Offset.AsInt); MetadataType tX64FieldStruct = _testModuleX64.GetType(_namespace, _type + "FieldStruct"); - MetadataType tX86FieldStruct = _testModuleX86.GetType(_namespace, _type + "FieldStruct"); + MetadataType tX86FieldStructWindows = _testModuleX86Windows.GetType(_namespace, _type + "FieldStruct"); + MetadataType tX86FieldStructUnix = _testModuleX86Unix.GetType(_namespace, _type + "FieldStruct"); MetadataType tARMFieldStruct = _testModuleARM.GetType(_namespace, _type + "FieldStruct"); Assert.Equal(0x8, tX64FieldStruct.GetField("_struct").Offset.AsInt); - Assert.Equal(0x4, tX86FieldStruct.GetField("_struct").Offset.AsInt); + Assert.Equal(0x4, tX86FieldStructWindows.GetField("_struct").Offset.AsInt); + Assert.Equal(0x4, tX86FieldStructUnix.GetField("_struct").Offset.AsInt); Assert.Equal(0x4, tARMFieldStruct.GetField("_struct").Offset.AsInt); } @@ -367,51 +443,63 @@ public void TestAlignmentBehavior_ShortByteEnumStructAuto() string _type = "ShortByteEnumStructAuto"; MetadataType tX64 = _testModuleX64.GetType(_namespace, _type); - MetadataType tX86 = _testModuleX86.GetType(_namespace, _type); + MetadataType tX86Windows = _testModuleX86Windows.GetType(_namespace, _type); + MetadataType tX86Unix = _testModuleX86Unix.GetType(_namespace, _type); MetadataType tARM = _testModuleARM.GetType(_namespace, _type); Assert.Equal(0x8, tX64.InstanceByteAlignment.AsInt); Assert.Equal(0x4, tARM.InstanceByteAlignment.AsInt); - Assert.Equal(0x4, tX86.InstanceByteAlignment.AsInt); + Assert.Equal(0x4, tX86Windows.InstanceByteAlignment.AsInt); + Assert.Equal(0x4, tX86Unix.InstanceByteAlignment.AsInt); Assert.Equal(0x8, tX64.InstanceByteCountUnaligned.AsInt); Assert.Equal(0x8, tARM.InstanceByteCountUnaligned.AsInt); - Assert.Equal(0x8, tX86.InstanceByteCountUnaligned.AsInt); + Assert.Equal(0x8, tX86Windows.InstanceByteCountUnaligned.AsInt); + Assert.Equal(0x8, tX86Unix.InstanceByteCountUnaligned.AsInt); Assert.Equal(0x8, tX64.InstanceByteCount.AsInt); Assert.Equal(0x8, tARM.InstanceByteCount.AsInt); - Assert.Equal(0x8, tX86.InstanceByteCount.AsInt); + Assert.Equal(0x8, tX86Windows.InstanceByteCount.AsInt); + Assert.Equal(0x8, tX86Unix.InstanceByteCount.AsInt); Assert.Equal(0x8, tX64.InstanceFieldAlignment.AsInt); Assert.Equal(0x4, tARM.InstanceFieldAlignment.AsInt); - Assert.Equal(0x4, tX86.InstanceFieldAlignment.AsInt); + Assert.Equal(0x4, tX86Windows.InstanceFieldAlignment.AsInt); + Assert.Equal(0x4, tX86Unix.InstanceFieldAlignment.AsInt); Assert.Equal(0x8, tX64.InstanceFieldSize.AsInt); Assert.Equal(0x8, tARM.InstanceFieldSize.AsInt); - Assert.Equal(0x8, tX86.InstanceFieldSize.AsInt); + Assert.Equal(0x8, tX86Windows.InstanceFieldSize.AsInt); + Assert.Equal(0x8, tX86Unix.InstanceFieldSize.AsInt); Assert.Equal(0x0, tX64.GetField("_1").Offset.AsInt); Assert.Equal(0x0, tARM.GetField("_1").Offset.AsInt); - Assert.Equal(0x0, tX86.GetField("_1").Offset.AsInt); + Assert.Equal(0x0, tX86Windows.GetField("_1").Offset.AsInt); + Assert.Equal(0x0, tX86Unix.GetField("_1").Offset.AsInt); Assert.Equal(0x4, tX64.GetField("_2").Offset.AsInt); Assert.Equal(0x4, tARM.GetField("_2").Offset.AsInt); - Assert.Equal(0x4, tX86.GetField("_2").Offset.AsInt); + Assert.Equal(0x4, tX86Windows.GetField("_2").Offset.AsInt); + Assert.Equal(0x4, tX86Unix.GetField("_2").Offset.AsInt); Assert.Equal(0x2, tX64.GetField("_3").Offset.AsInt); Assert.Equal(0x2, tARM.GetField("_3").Offset.AsInt); - Assert.Equal(0x2, tX86.GetField("_3").Offset.AsInt); + Assert.Equal(0x2, tX86Windows.GetField("_3").Offset.AsInt); + Assert.Equal(0x2, tX86Unix.GetField("_3").Offset.AsInt); Assert.Equal(0x5, tX64.GetField("_4").Offset.AsInt); Assert.Equal(0x5, tARM.GetField("_4").Offset.AsInt); - Assert.Equal(0x5, tX86.GetField("_4").Offset.AsInt); + Assert.Equal(0x5, tX86Windows.GetField("_4").Offset.AsInt); + Assert.Equal(0x5, tX86Unix.GetField("_4").Offset.AsInt); MetadataType tX64FieldStruct = _testModuleX64.GetType(_namespace, _type + "FieldStruct"); - MetadataType tX86FieldStruct = _testModuleX86.GetType(_namespace, _type + "FieldStruct"); + MetadataType tX86FieldStructWindows = _testModuleX86Windows.GetType(_namespace, _type + "FieldStruct"); + MetadataType tX86FieldStructUnix = _testModuleX86Unix.GetType(_namespace, _type + "FieldStruct"); MetadataType tARMFieldStruct = _testModuleARM.GetType(_namespace, _type + "FieldStruct"); Assert.Equal(0x8, tX64FieldStruct.GetField("_struct").Offset.AsInt); - Assert.Equal(0x4, tX86FieldStruct.GetField("_struct").Offset.AsInt); + Assert.Equal(0x4, tX86FieldStructWindows.GetField("_struct").Offset.AsInt); + Assert.Equal(0x4, tX86FieldStructUnix.GetField("_struct").Offset.AsInt); Assert.Equal(0x4, tARMFieldStruct.GetField("_struct").Offset.AsInt); } } diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/CanonicalizationTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/CanonicalizationTests.cs index d3f2c6c6036d67..e6fdfa03cba51d 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/CanonicalizationTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/CanonicalizationTests.cs @@ -25,7 +25,7 @@ public class CanonicalizationTests public CanonicalizationTests() { - _context = new TestTypeSystemContext(TargetArchitecture.Unknown); + _context = new TestTypeSystemContext(TargetArchitecture.Unknown, TargetOS.Unknown); var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly"); _context.SetSystemModule(systemModule); diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/CastingTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/CastingTests.cs index f6cd2e187d46c5..bbddda8a5fcf7d 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/CastingTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/CastingTests.cs @@ -14,7 +14,7 @@ public class CastingTests public CastingTests() { - _context = new TestTypeSystemContext(TargetArchitecture.X64); + _context = new TestTypeSystemContext(TargetArchitecture.X64, TargetOS.Unknown); var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly"); _context.SetSystemModule(systemModule); diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/ConstraintsValidationTest.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/ConstraintsValidationTest.cs index 3ea1408a96c102..7085817b5bdfdd 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/ConstraintsValidationTest.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/ConstraintsValidationTest.cs @@ -41,7 +41,7 @@ public class ConstraintsValidationTest public ConstraintsValidationTest() { - _context = new TestTypeSystemContext(TargetArchitecture.Unknown); + _context = new TestTypeSystemContext(TargetArchitecture.Unknown, TargetOS.Unknown); var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly"); _context.SetSystemModule(systemModule); diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/DefType.FieldLayoutTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/DefType.FieldLayoutTests.cs index c82f6c21a85be8..0fb1701c5369e3 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/DefType.FieldLayoutTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/DefType.FieldLayoutTests.cs @@ -14,7 +14,7 @@ public partial class DefTypeTests public DefTypeTests() { - var context = new TestTypeSystemContext(TargetArchitecture.X64); + var context = new TestTypeSystemContext(TargetArchitecture.X64, TargetOS.Unknown); var systemModule = context.CreateModuleForSimpleName("CoreTestAssembly"); context.SetSystemModule(systemModule); diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/GCPointerMapTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/GCPointerMapTests.cs index 51578a171105a8..a3fc1a791db0c5 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/GCPointerMapTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/GCPointerMapTests.cs @@ -14,7 +14,7 @@ public partial class GCPointerMapTests public GCPointerMapTests() { - _context = new TestTypeSystemContext(TargetArchitecture.X86); + _context = new TestTypeSystemContext(TargetArchitecture.X86, TargetOS.Unknown); var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly"); _context.SetSystemModule(systemModule); diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/GenericTypeAndMethodTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/GenericTypeAndMethodTests.cs index c9224fa7d9dbd6..465773a6a2a83d 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/GenericTypeAndMethodTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/GenericTypeAndMethodTests.cs @@ -14,7 +14,7 @@ public class GenericMethodTests public GenericMethodTests() { - _context = new TestTypeSystemContext(TargetArchitecture.Unknown); + _context = new TestTypeSystemContext(TargetArchitecture.Unknown, TargetOS.Unknown); var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly"); _context.SetSystemModule(systemModule); diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/HashcodeTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/HashcodeTests.cs index a9451752da9b98..868b641de94ffa 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/HashcodeTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/HashcodeTests.cs @@ -17,7 +17,7 @@ public class HashcodeTests public HashcodeTests() { - _context = new TestTypeSystemContext(TargetArchitecture.X64); + _context = new TestTypeSystemContext(TargetArchitecture.X64, TargetOS.Unknown); var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly"); _context.SetSystemModule(systemModule); diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/ILDisassemblerTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/ILDisassemblerTests.cs index 45881020f622ae..9b211c52f36e0f 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/ILDisassemblerTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/ILDisassemblerTests.cs @@ -18,7 +18,7 @@ public class ILDisassemblerTests public ILDisassemblerTests() { - _context = new TestTypeSystemContext(TargetArchitecture.X64); + _context = new TestTypeSystemContext(TargetArchitecture.X64, TargetOS.Unknown); var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly"); _context.SetSystemModule(systemModule); diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/InstanceFieldLayoutTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/InstanceFieldLayoutTests.cs index 942021d77bfa1b..ef0da110b02e55 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/InstanceFieldLayoutTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/InstanceFieldLayoutTests.cs @@ -17,7 +17,7 @@ public class InstanceFieldLayoutTests public InstanceFieldLayoutTests() { - _context = new TestTypeSystemContext(TargetArchitecture.X64); + _context = new TestTypeSystemContext(TargetArchitecture.X64, TargetOS.Unknown); var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly"); _context.SetSystemModule(systemModule); diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/InterfacesTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/InterfacesTests.cs index 683138a8823508..06854e7f65b94b 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/InterfacesTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/InterfacesTests.cs @@ -16,7 +16,7 @@ public class InterfacesTests public InterfacesTests() { - _context = new TestTypeSystemContext(TargetArchitecture.X64); + _context = new TestTypeSystemContext(TargetArchitecture.X64, TargetOS.Unknown); var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly"); _context.SetSystemModule(systemModule); diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/MarshalUtilsTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/MarshalUtilsTests.cs index c3befa87af72d4..00cc1379d70ecc 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/MarshalUtilsTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/MarshalUtilsTests.cs @@ -15,7 +15,7 @@ public class MarshalUtilsTests public MarshalUtilsTests() { - _context = new TestTypeSystemContext(TargetArchitecture.X64); + _context = new TestTypeSystemContext(TargetArchitecture.X64, TargetOS.Unknown); var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly"); _context.SetSystemModule(systemModule); diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/RuntimeDeterminedTypesTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/RuntimeDeterminedTypesTests.cs index a394a562af9f5f..bfbe0eae1f85e2 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/RuntimeDeterminedTypesTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/RuntimeDeterminedTypesTests.cs @@ -23,7 +23,7 @@ public class RuntimeDeterminedTypesTests public RuntimeDeterminedTypesTests() { - _context = new TestTypeSystemContext(TargetArchitecture.Unknown); + _context = new TestTypeSystemContext(TargetArchitecture.Unknown, TargetOS.Unknown); var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly"); _context.SetSystemModule(systemModule); diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/SignatureTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/SignatureTests.cs index 0ea96171119616..c757d6cb731dfd 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/SignatureTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/SignatureTests.cs @@ -27,7 +27,7 @@ public class SignatureTests public SignatureTests(ITestOutputHelper output) { _output = output; - _context = new TestTypeSystemContext(TargetArchitecture.X64); + _context = new TestTypeSystemContext(TargetArchitecture.X64, TargetOS.Unknown); var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly"); _context.SetSystemModule(systemModule); @@ -140,7 +140,7 @@ public void TestSerializedSignatureWithArrayShapes() // Create new TypeSystemContext with just created assembly inside - var lookupContext = new TestTypeSystemContext(TargetArchitecture.X64); + var lookupContext = new TestTypeSystemContext(TargetArchitecture.X64, TargetOS.Unknown); var systemModule = lookupContext.CreateModuleForSimpleName("CoreTestAssembly"); lookupContext.SetSystemModule(systemModule); @@ -168,7 +168,7 @@ public void TestSerializedSignatureWithReferenceToMDIntArray() // Create new TypeSystemContext with just created assembly inside - var lookupContext = new TestTypeSystemContext(TargetArchitecture.X64); + var lookupContext = new TestTypeSystemContext(TargetArchitecture.X64, TargetOS.Unknown); var systemModule = lookupContext.CreateModuleForSimpleName("CoreTestAssembly"); lookupContext.SetSystemModule(systemModule); lookupContext.CreateModuleForSimpleName("Lookup", peStream); diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/StaticFieldLayoutTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/StaticFieldLayoutTests.cs index 421313c8dc6579..b882ecffb7eefd 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/StaticFieldLayoutTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/StaticFieldLayoutTests.cs @@ -19,7 +19,7 @@ public class StaticFieldLayoutTests public StaticFieldLayoutTests() { - _context = new TestTypeSystemContext(TargetArchitecture.X64); + _context = new TestTypeSystemContext(TargetArchitecture.X64, TargetOS.Unknown); var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly"); _context.SetSystemModule(systemModule); diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/SyntheticVirtualOverrideTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/SyntheticVirtualOverrideTests.cs index 9fc3b9bf7d0d0b..ea2eeb409d6c67 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/SyntheticVirtualOverrideTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/SyntheticVirtualOverrideTests.cs @@ -110,7 +110,7 @@ private class SyntheticVirtualOverrideTypeSystemContext : TestTypeSystemContext private Dictionary _equalsMethods = new Dictionary(); public SyntheticVirtualOverrideTypeSystemContext() - : base(TargetArchitecture.Unknown) + : base(TargetArchitecture.Unknown, TargetOS.Unknown) { } diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/TestTypeSystemContext.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/TestTypeSystemContext.cs index 0fbd0b6a35329e..1287730119be02 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/TestTypeSystemContext.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/TestTypeSystemContext.cs @@ -29,8 +29,8 @@ class TestTypeSystemContext : MetadataTypeSystemContext public CanonicalizationMode CanonMode { get; set; } = CanonicalizationMode.RuntimeDetermined; - public TestTypeSystemContext(TargetArchitecture arch) - : base(new TargetDetails(arch, TargetOS.Unknown, TargetAbi.Unknown)) + public TestTypeSystemContext(TargetArchitecture arch, TargetOS os) + : base(new TargetDetails(arch, os, TargetAbi.Unknown)) { } diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/TypeNameParsingTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/TypeNameParsingTests.cs index d7a08bf583d505..23078c2d6fa902 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/TypeNameParsingTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/TypeNameParsingTests.cs @@ -31,7 +31,7 @@ public class TypeNameParsingTests public TypeNameParsingTests() { - _context = new TestTypeSystemContext(TargetArchitecture.X64); + _context = new TestTypeSystemContext(TargetArchitecture.X64, TargetOS.Unknown); // TODO-NICE: split test types into a separate, non-core, module _testModule = _context.CreateModuleForSimpleName("CoreTestAssembly"); diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/UniversalGenericFieldLayoutTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/UniversalGenericFieldLayoutTests.cs index c0680f2ebbb2d5..5e3ac590000f99 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/UniversalGenericFieldLayoutTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/UniversalGenericFieldLayoutTests.cs @@ -22,19 +22,19 @@ public class UniversalGenericFieldLayoutTests public UniversalGenericFieldLayoutTests() { // Architecture specific tests may use these contexts - _contextX64 = new TestTypeSystemContext(TargetArchitecture.X64); + _contextX64 = new TestTypeSystemContext(TargetArchitecture.X64, TargetOS.Unknown); var systemModuleX64 = _contextX64.CreateModuleForSimpleName("CoreTestAssembly"); _contextX64.SetSystemModule(systemModuleX64); _testModuleX64 = systemModuleX64; - _contextARM = new TestTypeSystemContext(TargetArchitecture.ARM); + _contextARM = new TestTypeSystemContext(TargetArchitecture.ARM, TargetOS.Unknown); var systemModuleARM = _contextARM.CreateModuleForSimpleName("CoreTestAssembly"); _contextARM.SetSystemModule(systemModuleARM); _testModuleARM = systemModuleARM; - _contextX86 = new TestTypeSystemContext(TargetArchitecture.X86); + _contextX86 = new TestTypeSystemContext(TargetArchitecture.X86, TargetOS.Unknown); var systemModuleX86 = _contextX86.CreateModuleForSimpleName("CoreTestAssembly"); _contextX86.SetSystemModule(systemModuleX86); diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/ValueTypeShapeCharacteristicsTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/ValueTypeShapeCharacteristicsTests.cs index 2971fd468ead31..9adc169f41d394 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/ValueTypeShapeCharacteristicsTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/ValueTypeShapeCharacteristicsTests.cs @@ -17,7 +17,7 @@ public class ValueTypeShapeCharacteristicsTests public ValueTypeShapeCharacteristicsTests() { - _context = new TestTypeSystemContext(TargetArchitecture.ARM); + _context = new TestTypeSystemContext(TargetArchitecture.ARM, TargetOS.Unknown); var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly"); _context.SetSystemModule(systemModule); diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/VirtualFunctionOverrideTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/VirtualFunctionOverrideTests.cs index 938377d8cd3c9c..5349d60c44c97b 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/VirtualFunctionOverrideTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/VirtualFunctionOverrideTests.cs @@ -19,7 +19,7 @@ public class VirtualFunctionOverrideTests public VirtualFunctionOverrideTests() { - _context = new TestTypeSystemContext(TargetArchitecture.X64); + _context = new TestTypeSystemContext(TargetArchitecture.X64, TargetOS.Unknown); var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly"); _context.SetSystemModule(systemModule); diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/WellKnownTypeTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/WellKnownTypeTests.cs index 3f2f4c2b4d31ea..90880fb81417d3 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/WellKnownTypeTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.ReadyToRun.Tests/WellKnownTypeTests.cs @@ -14,7 +14,7 @@ public class WellKnownTypeTests public WellKnownTypeTests() { - _context = new TestTypeSystemContext(TargetArchitecture.X64); + _context = new TestTypeSystemContext(TargetArchitecture.X64, TargetOS.Unknown); var systemModule = _context.CreateModuleForSimpleName("CoreTestAssembly"); _context.SetSystemModule(systemModule); diff --git a/src/coreclr/tools/aot/crossgen2.sln b/src/coreclr/tools/aot/crossgen2.sln index ac541c0a78d16a..d19aa6f3db70da 100644 --- a/src/coreclr/tools/aot/crossgen2.sln +++ b/src/coreclr/tools/aot/crossgen2.sln @@ -114,8 +114,8 @@ Global {3EACD929-4725-4173-A845-734936BBDF87}.Debug|Any CPU.Build.0 = Debug|Any CPU {3EACD929-4725-4173-A845-734936BBDF87}.Debug|x64.ActiveCfg = Debug|x64 {3EACD929-4725-4173-A845-734936BBDF87}.Debug|x64.Build.0 = Debug|x64 - {3EACD929-4725-4173-A845-734936BBDF87}.Debug|x86.ActiveCfg = Debug|Any CPU - {3EACD929-4725-4173-A845-734936BBDF87}.Debug|x86.Build.0 = Debug|Any CPU + {3EACD929-4725-4173-A845-734936BBDF87}.Debug|x86.ActiveCfg = Debug|x86 + {3EACD929-4725-4173-A845-734936BBDF87}.Debug|x86.Build.0 = Debug|x86 {3EACD929-4725-4173-A845-734936BBDF87}.Release|Any CPU.ActiveCfg = Release|Any CPU {3EACD929-4725-4173-A845-734936BBDF87}.Release|Any CPU.Build.0 = Release|Any CPU {3EACD929-4725-4173-A845-734936BBDF87}.Release|x64.ActiveCfg = Release|Any CPU diff --git a/src/coreclr/vm/class.h b/src/coreclr/vm/class.h index 300ed225ebc28c..953a3c5751303b 100644 --- a/src/coreclr/vm/class.h +++ b/src/coreclr/vm/class.h @@ -388,7 +388,9 @@ class EEClassLayoutInfo // explicit type inherits from this type. e_ZERO_SIZED = 0x04, // The size of the struct is explicitly specified in the meta-data. - e_HAS_EXPLICIT_SIZE = 0x08 + e_HAS_EXPLICIT_SIZE = 0x08, + // Class layout is certain to contain no GC pointers + e_LAYOUT_CONTAINS_NO_GC_POINTERS = 0x10, }; BYTE m_bFlags; @@ -409,6 +411,12 @@ class EEClassLayoutInfo return (m_bFlags & e_BLITTABLE) == e_BLITTABLE; } + bool LayoutContainsNoGCPointers() const + { + LIMITED_METHOD_CONTRACT; + return (m_bFlags & e_LAYOUT_CONTAINS_NO_GC_POINTERS) == e_LAYOUT_CONTAINS_NO_GC_POINTERS; + } + BOOL IsManagedSequential() const { LIMITED_METHOD_CONTRACT; @@ -438,6 +446,11 @@ class EEClassLayoutInfo return m_cbPackingSize; } + static BOOL TryGetPrimitiveFieldSizeAndAlignment( + CorElementType corElemType, + /* out */ UINT32 *size, + /* out */ UINT32 *alignment); + private: void SetIsBlittable(BOOL isBlittable) { @@ -446,6 +459,13 @@ class EEClassLayoutInfo : (m_bFlags & ~e_BLITTABLE); } + void SetLayoutContainsNoGCPointers(BOOL layoutContainsNoGCPointers) + { + LIMITED_METHOD_CONTRACT; + m_bFlags = layoutContainsNoGCPointers ? (m_bFlags | e_LAYOUT_CONTAINS_NO_GC_POINTERS) + : (m_bFlags & ~e_LAYOUT_CONTAINS_NO_GC_POINTERS); + } + void SetIsManagedSequential(BOOL isManagedSequential) { LIMITED_METHOD_CONTRACT; @@ -758,6 +778,12 @@ class EEClass // DO NOT CREATE A NEW EEClass USING NEW! // class is blittable BOOL IsBlittable(); + // Class is certain to contain no GC pointers; this method shall return TRUE for all blittable + // classes but not all classes with no GC pointers are blittable. This method exactly + // matches the behavior of MethodTable::ContainsPointers except in the presence of fields + // with generic types where this function always returns FALSE. + BOOL LayoutContainsNoGCPointers(); + #ifndef DACCESS_COMPILE void *operator new(size_t size, LoaderHeap* pHeap, AllocMemTracker *pamTracker); void Destruct(MethodTable * pMT); @@ -2091,6 +2117,12 @@ inline BOOL EEClass::IsBlittable() return (HasLayout() && GetLayoutInfo()->IsBlittable()); } +inline BOOL EEClass::LayoutContainsNoGCPointers() +{ + LIMITED_METHOD_CONTRACT; + return (HasLayout() && GetLayoutInfo()->LayoutContainsNoGCPointers()); +} + inline BOOL EEClass::IsManagedSequential() { LIMITED_METHOD_CONTRACT; diff --git a/src/coreclr/vm/classlayoutinfo.cpp b/src/coreclr/vm/classlayoutinfo.cpp index 612c119be79f01..a30b0e53f5d4b1 100644 --- a/src/coreclr/vm/classlayoutinfo.cpp +++ b/src/coreclr/vm/classlayoutinfo.cpp @@ -190,6 +190,7 @@ namespace calcTotalSize = fieldEnd; } + bool useMetadataClassSize = false; if (classSizeInMetadata != 0) { ULONG classSize = classSizeInMetadata; @@ -197,17 +198,26 @@ namespace COMPlusThrowOM(); // size must be large enough to accomodate layout. If not, we use the layout size instead. - calcTotalSize = max(classSize, calcTotalSize); + if (classSize >= calcTotalSize) + { + calcTotalSize = classSize; + useMetadataClassSize = true; + } } - else + + if (!useMetadataClassSize) { + uint32_t sizeAlignment = LargestAlignmentRequirement; +#if !defined(TARGET_64BIT) && !defined(FEATURE_64BIT_ALIGNMENT) + sizeAlignment = min(sizeAlignment, TARGET_POINTER_SIZE); +#endif // There was no class size given in metadata, so let's round up to a multiple of the alignment requirement // to make array allocations of this structure simple to keep aligned. - calcTotalSize += (LargestAlignmentRequirement - calcTotalSize % LargestAlignmentRequirement) % LargestAlignmentRequirement; + calcTotalSize += (sizeAlignment - calcTotalSize % sizeAlignment) % sizeAlignment; - if (calcTotalSize % LargestAlignmentRequirement != 0) + if (calcTotalSize % sizeAlignment != 0) { - if (!SafeAddUINT32(&calcTotalSize, LargestAlignmentRequirement - (calcTotalSize % LargestAlignmentRequirement))) + if (!SafeAddUINT32(&calcTotalSize, sizeAlignment - (calcTotalSize % sizeAlignment))) COMPlusThrowOM(); } } @@ -236,42 +246,9 @@ namespace //======================================================================= BOOL CheckIfDisqualifiedFromManagedSequential(CorElementType corElemType, MetaSig& fsig, RawFieldPlacementInfo* pManagedPlacementInfo) { - pManagedPlacementInfo->m_alignment = TARGET_POINTER_SIZE; - pManagedPlacementInfo->m_size = TARGET_POINTER_SIZE; - // This type may qualify for ManagedSequential. Collect managed size and alignment info. - if (CorTypeInfo::IsPrimitiveType(corElemType)) - { - // Safe cast - no primitive type is larger than 4gb! - pManagedPlacementInfo->m_size = ((UINT32)CorTypeInfo::Size(corElemType)); -#if defined(TARGET_X86) && defined(UNIX_X86_ABI) - switch (corElemType) - { - // The System V ABI for i386 defines different packing for these types. - case ELEMENT_TYPE_I8: - case ELEMENT_TYPE_U8: - case ELEMENT_TYPE_R8: - { - pManagedPlacementInfo->m_alignment = 4; - break; - } - - default: - { - pManagedPlacementInfo->m_alignment = pManagedPlacementInfo->m_size; - break; - } - } -#else // TARGET_X86 && UNIX_X86_ABI - pManagedPlacementInfo->m_alignment = pManagedPlacementInfo->m_size; -#endif - - return FALSE; - } - else if (corElemType == ELEMENT_TYPE_PTR) + if (EEClassLayoutInfo::TryGetPrimitiveFieldSizeAndAlignment(corElemType, + &pManagedPlacementInfo->m_alignment, &pManagedPlacementInfo->m_size)) { - pManagedPlacementInfo->m_size = TARGET_POINTER_SIZE; - pManagedPlacementInfo->m_alignment = TARGET_POINTER_SIZE; - return FALSE; } else if (corElemType == ELEMENT_TYPE_VALUETYPE) @@ -285,6 +262,13 @@ namespace if (pNestedType.GetMethodTable()->HasLayout()) { pManagedPlacementInfo->m_alignment = pNestedType.GetMethodTable()->GetLayoutInfo()->m_ManagedLargestAlignmentRequirementOfAllMembers; +#if !defined(FEATURE_64BIT_ALIGNMENT) && !defined(TARGET_64BIT) + // On x86, maximum native struct alignment is 4 + if (!pNestedType.GetMethodTable()->IsEnum() && pManagedPlacementInfo->m_alignment > TARGET_POINTER_SIZE) + { + pManagedPlacementInfo->m_alignment = TARGET_POINTER_SIZE; + } +#endif } else { @@ -298,6 +282,46 @@ namespace return TRUE; } + //======================================================================= + // This function returns TRUE if the provided type contains no GC pointers. + // The fsig parameter is used when the corElemType doesn't contain enough information + // (for ELEMENT_TYPE_VALUETYPE). For generics we cannot confirm that the type + // contains no GC pointers because we don't have enough information to check that. + //======================================================================= + BOOL CheckIfFieldContainsNoGCPointers(CorElementType corElemType, MetaSig& fsig) + { + switch (corElemType) + { + case ELEMENT_TYPE_VOID: + case ELEMENT_TYPE_BOOLEAN: + case ELEMENT_TYPE_CHAR: + case ELEMENT_TYPE_I1: + case ELEMENT_TYPE_U1: + case ELEMENT_TYPE_I2: + case ELEMENT_TYPE_U2: + case ELEMENT_TYPE_I4: + case ELEMENT_TYPE_U4: + case ELEMENT_TYPE_I8: + case ELEMENT_TYPE_U8: + case ELEMENT_TYPE_R4: + case ELEMENT_TYPE_R8: + case ELEMENT_TYPE_I: + case ELEMENT_TYPE_U: + case ELEMENT_TYPE_PTR: + case ELEMENT_TYPE_FNPTR: + return TRUE; + + case ELEMENT_TYPE_VALUETYPE: + return fsig.GetLastTypeHandleThrowing(ClassLoader::LoadTypes, + CLASS_LOAD_APPROXPARENTS, + TRUE).GetMethodTable()->LayoutContainsNoGCPointers(); + + default: + // For no other types we can prove that they don't contain GC pointers + return FALSE; + } + } + #ifdef UNIX_AMD64_ABI void SystemVAmd64CheckForPassNativeStructInRegister(MethodTable* pMT, EEClassNativeLayoutInfo* pNativeLayoutInfo) { @@ -425,6 +449,7 @@ namespace BOOL* fDisqualifyFromManagedSequential, LayoutRawFieldInfo* pFieldInfoArrayOut, BOOL* pIsBlittableOut, + BOOL* pLayoutContainsNoGCPointers, ULONG* cInstanceFields #ifdef _DEBUG , @@ -493,8 +518,8 @@ namespace CorElementType corElemType = fsig.NextArgNormalized(); *fDisqualifyFromManagedSequential |= CheckIfDisqualifiedFromManagedSequential(corElemType, fsig, &pFieldInfoArrayOut->m_placement); - if (!IsFieldBlittable(pModule, fd, fsig.GetArgProps(), pTypeContext, nativeTypeFlags)) - *pIsBlittableOut = FALSE; + *pIsBlittableOut = *pIsBlittableOut && IsFieldBlittable(pModule, fd, fsig.GetArgProps(), pTypeContext, nativeTypeFlags); + *pLayoutContainsNoGCPointers = *pLayoutContainsNoGCPointers && CheckIfFieldContainsNoGCPointers(corElemType, fsig); (*cInstanceFields)++; pFieldInfoArrayOut++; @@ -537,6 +562,61 @@ namespace #endif // FEATURE_HFA } +//======================================================================= +// This function calculates the side and alignment information for primitive +// fields. The function returns TRUE when it succeeds i.e. when it managed +// to resolve the primitive type. +//======================================================================= +BOOL EEClassLayoutInfo::TryGetPrimitiveFieldSizeAndAlignment(CorElementType corElemType, /* out */ UINT32 *size, /* out */ UINT32 *alignment) +{ + CONTRACTL + { + PRECONDITION(CheckPointer(size)); + PRECONDITION(CheckPointer(alignment)); + } + CONTRACTL_END; + + *alignment = TARGET_POINTER_SIZE; + *size = TARGET_POINTER_SIZE; + if (CorTypeInfo::IsPrimitiveType(corElemType)) + { + // Safe cast - no primitive type is larger than 4gb! + *size = ((UINT32)CorTypeInfo::Size(corElemType)); +#if defined(TARGET_X86) && defined(UNIX_X86_ABI) + switch (corElemType) + { + // The System V ABI for i386 defines different packing for these types. + case ELEMENT_TYPE_I8: + case ELEMENT_TYPE_U8: + case ELEMENT_TYPE_R8: + { + *alignment = 4; + break; + } + + default: + { + *alignment = size; + break; + } + } +#else // TARGET_X86 && UNIX_X86_ABI + *alignment = *size; +#endif + + return TRUE; + } + else if (corElemType == ELEMENT_TYPE_PTR) + { + *size = TARGET_POINTER_SIZE; + *alignment = TARGET_POINTER_SIZE; + + return TRUE; + } + + return FALSE; +} + //======================================================================= // Called from the clsloader to load up and summarize the field metadata // for layout classes. @@ -614,6 +694,7 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing( BOOL fParentHasLayout = pParentMT && pParentMT->HasLayout(); UINT32 cbAdjustedParentLayoutSize = 0; EEClassLayoutInfo *pParentLayoutInfo = NULL; + BOOL layoutContainsNoGCPointers = TRUE; if (fParentHasLayout) { pParentLayoutInfo = pParentMT->GetLayoutInfo(); @@ -628,6 +709,7 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing( { cbAdjustedParentLayoutSize = pParentMT->GetNumInstanceFieldBytes(); } + layoutContainsNoGCPointers = pParentMT->LayoutContainsNoGCPointers(); } ULONG cInstanceFields = 0; @@ -647,6 +729,7 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing( &fDisqualifyFromManagedSequential, pInfoArrayOut, &isBlittable, + &layoutContainsNoGCPointers, &cInstanceFields DEBUGARG(cTotalFields) DEBUGARG(szNamespace) @@ -660,6 +743,7 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing( && (!pParentLayoutInfo || !pParentLayoutInfo->IsZeroSized()); // Ensure non-zero size } pEEClassLayoutInfoOut->SetIsBlittable(isBlittable); + pEEClassLayoutInfoOut->SetLayoutContainsNoGCPointers(layoutContainsNoGCPointers); S_UINT32 cbSortArraySize = S_UINT32(cTotalFields) * S_UINT32(sizeof(LayoutRawFieldInfo*)); if (cbSortArraySize.IsOverflow()) @@ -690,7 +774,7 @@ VOID EEClassLayoutInfo::CollectLayoutFieldMetadataThrowing( } BYTE parentManagedAlignmentRequirement = 0; - if (pParentMT && (pParentMT->IsManagedSequential() || (pParentMT->GetClass()->HasExplicitFieldOffsetLayout() && pParentMT->IsBlittable()))) + if (pParentMT && pParentMT->LayoutContainsNoGCPointers()) { parentManagedAlignmentRequirement = pParentLayoutInfo->m_ManagedLargestAlignmentRequirementOfAllMembers; } diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index e98a43973ce757..9822315be0aaf8 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -13524,7 +13524,7 @@ void ComputeGCRefMap(MethodTable * pMT, BYTE * pGCRefMap, size_t cbGCRefMap) // - Alignment // - Position of GC references // -BOOL TypeLayoutCheck(MethodTable * pMT, PCCOR_SIGNATURE pBlob) +BOOL TypeLayoutCheck(MethodTable * pMT, PCCOR_SIGNATURE pBlob, BOOL printDiff) { STANDARD_VM_CONTRACT; @@ -13534,13 +13534,28 @@ BOOL TypeLayoutCheck(MethodTable * pMT, PCCOR_SIGNATURE pBlob) uint32_t dwFlags; IfFailThrow(p.GetData(&dwFlags)); + BOOL result = TRUE; + // Size is checked unconditionally uint32_t dwExpectedSize; IfFailThrow(p.GetData(&dwExpectedSize)); DWORD dwActualSize = pMT->GetNumInstanceFieldBytes(); if (dwExpectedSize != dwActualSize) - return FALSE; + { + if (printDiff) + { + result = FALSE; + + DefineFullyQualifiedNameForClassW(); + wprintf(W("Type %s: expected size 0x%08x, actual size 0x%08x\n"), + GetFullyQualifiedNameForClassW(pMT), dwExpectedSize, dwActualSize); + } + else + { + return FALSE; + } + } #ifdef FEATURE_HFA if (dwFlags & READYTORUN_LAYOUT_HFA) @@ -13550,12 +13565,38 @@ BOOL TypeLayoutCheck(MethodTable * pMT, PCCOR_SIGNATURE pBlob) DWORD dwActualHFAType = pMT->GetHFAType(); if (dwExpectedHFAType != dwActualHFAType) - return FALSE; + { + if (printDiff) + { + result = FALSE; + + DefineFullyQualifiedNameForClassW(); + wprintf(W("Type %s: expected HFA type %08x, actual %08x\n"), + GetFullyQualifiedNameForClassW(pMT), dwExpectedHFAType, dwActualHFAType); + } + else + { + return FALSE; + } + } } else { if (pMT->IsHFA()) - return FALSE; + { + if (printDiff) + { + result = FALSE; + + DefineFullyQualifiedNameForClassW(); + wprintf(W("Type %s: type is HFA but READYTORUN_LAYOUT_HFA flag is not set\n"), + GetFullyQualifiedNameForClassW(pMT)); + } + else + { + return FALSE; + } + } } #else _ASSERTE(!(dwFlags & READYTORUN_LAYOUT_HFA)); @@ -13571,7 +13612,20 @@ BOOL TypeLayoutCheck(MethodTable * pMT, PCCOR_SIGNATURE pBlob) DWORD dwActualAlignment = CEEInfo::getClassAlignmentRequirementStatic(pMT); if (dwExpectedAlignment != dwActualAlignment) - return FALSE; + { + if (printDiff) + { + result = FALSE; + + DefineFullyQualifiedNameForClassW(); + wprintf(W("Type %s: expected alignment 0x%08x, actual 0x%08x\n"), + GetFullyQualifiedNameForClassW(pMT), dwExpectedAlignment, dwActualAlignment); + } + else + { + return FALSE; + } + } } @@ -13580,7 +13634,20 @@ BOOL TypeLayoutCheck(MethodTable * pMT, PCCOR_SIGNATURE pBlob) if (dwFlags & READYTORUN_LAYOUT_GCLayout_Empty) { if (pMT->ContainsPointers()) - return FALSE; + { + if (printDiff) + { + result = FALSE; + + DefineFullyQualifiedNameForClassW(); + wprintf(W("Type %s contains pointers but READYTORUN_LAYOUT_GCLayout_Empty is set\n"), + GetFullyQualifiedNameForClassW(pMT)); + } + else + { + return FALSE; + } + } } else { @@ -13592,11 +13659,24 @@ BOOL TypeLayoutCheck(MethodTable * pMT, PCCOR_SIGNATURE pBlob) ComputeGCRefMap(pMT, pGCRefMap, cbGCRefMap); if (memcmp(pGCRefMap, p.GetPtr(), cbGCRefMap) != 0) - return FALSE; + { + if (printDiff) + { + result = FALSE; + + DefineFullyQualifiedNameForClassW(); + wprintf(W("Type %s: GC refmap content doesn't match\n"), + GetFullyQualifiedNameForClassW(pMT)); + } + else + { + return FALSE; + } + } } } - return TRUE; + return result; } #endif // FEATURE_READYTORUN @@ -14049,7 +14129,7 @@ BOOL LoadDynamicInfoEntry(Module *currentModule, MethodTable * pMT = th.AsMethodTable(); _ASSERTE(pMT->IsValueType()); - if (!TypeLayoutCheck(pMT, pBlob)) + if (!TypeLayoutCheck(pMT, pBlob, /* printDiff */ kind == ENCODE_VERIFY_TYPE_LAYOUT)) { if (kind == ENCODE_CHECK_TYPE_LAYOUT) { @@ -14068,7 +14148,7 @@ BOOL LoadDynamicInfoEntry(Module *currentModule, StackScratchBuffer buf; _ASSERTE_MSG(false, fatalErrorString.GetUTF8(buf)); // Run through the type layout logic again, after the assert, makes debugging easy - TypeLayoutCheck(pMT, pBlob); + TypeLayoutCheck(pMT, pBlob, /* printDiff */ TRUE); } #endif diff --git a/src/coreclr/vm/methodtable.h b/src/coreclr/vm/methodtable.h index 326bcce2c42ce3..c73eefa52e1555 100644 --- a/src/coreclr/vm/methodtable.h +++ b/src/coreclr/vm/methodtable.h @@ -1660,6 +1660,8 @@ class MethodTable inline BOOL IsBlittable(); + inline BOOL LayoutContainsNoGCPointers(); + inline BOOL IsManagedSequential(); inline BOOL HasExplicitSize(); diff --git a/src/coreclr/vm/methodtable.inl b/src/coreclr/vm/methodtable.inl index 88ebe105bda5cf..3c0315d3044fcc 100644 --- a/src/coreclr/vm/methodtable.inl +++ b/src/coreclr/vm/methodtable.inl @@ -440,6 +440,19 @@ inline BOOL MethodTable::IsBlittable() #endif // DACCESS_COMPILE } +//========================================================================================== +inline BOOL MethodTable::LayoutContainsNoGCPointers() +{ + WRAPPER_NO_CONTRACT; +#ifndef DACCESS_COMPILE + _ASSERTE(GetClass()); + return GetClass()->LayoutContainsNoGCPointers(); +#else // DACCESS_COMPILE + DacNotImpl(); + return false; +#endif // DACCESS_COMPILE +} + //========================================================================================== inline BOOL MethodTable::HasClassConstructor() { diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index c3b028bf0141a3..c9b53607f95cda 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -1718,27 +1718,11 @@ MethodTableBuilder::BuildMethodTableThrowing( GetNumStaticFields(), GetNumHandleRegularStatics() + GetNumHandleThreadStatics(), pszDebugName)); - if (IsBlittable() || IsManagedSequential()) - { - bmtFP->NumGCPointerSeries = 0; - bmtFP->NumInstanceGCPointerFields = 0; - - _ASSERTE(HasLayout()); - - bmtFP->NumInstanceFieldBytes = GetLayoutInfo()->m_cbManagedSize; + // To avoid breaking interop we need to ensure that blittable types may not contain GC pointers. + ASSERT(!IsBlittable() || LayoutContainsNoGCPointers()); - // For simple Blittable types we still need to check if they have any overlapping - // fields and call the method SetHasOverLayedFields() when they are detected. - // - if (HasExplicitFieldOffsetLayout()) - { - _ASSERTE(!bmtGenerics->fContainsGenericVariables); // A simple Blittable type can't ever be an open generic type. - HandleExplicitLayout(pByValueClassCache); - } - } - else + if (!bmtGenerics->fContainsGenericVariables && HasExplicitFieldOffsetLayout()) { - _ASSERTE(!IsBlittable()); // HandleExplicitLayout fails for the GenericTypeDefinition when // it will succeed for some particular instantiations. // Thus we only do explicit layout for real instantiations, e.g. C, not @@ -1746,15 +1730,16 @@ MethodTableBuilder::BuildMethodTableThrowing( // of the "fake" types involving generic type variables which are // used for reflection and verification, e.g. C>. // - if (!bmtGenerics->fContainsGenericVariables && HasExplicitFieldOffsetLayout()) - { - HandleExplicitLayout(pByValueClassCache); - } - else - { - // Place instance fields - PlaceInstanceFields(pByValueClassCache); - } + HandleExplicitLayout(pByValueClassCache); + } + else if (LayoutContainsNoGCPointers()) + { + bmtFP->NumInstanceFieldBytes = GetLayoutInfo()->m_cbManagedSize; + } + else + { + // Place instance fields + PlaceInstanceFields(pByValueClassCache); } if (CheckIfSIMDAndUpdateSize()) @@ -1845,8 +1830,11 @@ MethodTableBuilder::BuildMethodTableThrowing( // Perform relevant GC calculations for value classes HandleGCForValueClasses(pByValueClassCache); - // GC reqires the series to be sorted. - // TODO: fix it so that we emit them in the correct order in the first place. + // If we end up concluding that a type contains GC pointers we shouldn't have ruled that out beforehand. + ASSERT(!(pMT->ContainsPointers() && LayoutContainsNoGCPointers())); + + // GC requires the series to be sorted. + // TODO: fix it so that we emit them in the correct order in the first place. if (pMT->ContainsPointers()) { CGCDesc* gcDesc = CGCDesc::GetCGCDescFromMT(pMT); @@ -4256,8 +4244,7 @@ VOID MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList, // if (fIsByValue) { - if (!fIsStatic && - (IsBlittable() || HasExplicitFieldOffsetLayout())) + if (!fIsStatic && HasExplicitFieldOffsetLayout()) { (DWORD_PTR &)pFD->m_pMTOfEnclosingClass = (*pByValueClassCache)[dwCurrentDeclaredField]->GetNumInstanceFieldBytes(); @@ -4267,7 +4254,7 @@ VOID MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList, else pFD->SetOffset(FIELD_OFFSET_VALUE_CLASS); } - else if (!fIsStatic && IsManagedSequential()) + else if (!fIsStatic && LayoutContainsNoGCPointers()) { (DWORD_PTR &)pFD->m_pMTOfEnclosingClass = (*pByValueClassCache)[dwCurrentDeclaredField]->GetNumInstanceFieldBytes(); @@ -4292,9 +4279,9 @@ VOID MethodTableBuilder::InitializeFieldDescs(FieldDesc *pFieldDescList, // If there is any kind of explicit layout information for this field, use it. If not, then // mark it as either GC or non-GC and as unplaced; it will get placed later on in an optimized way. - if ((IsBlittable() || HasExplicitFieldOffsetLayout()) && !fIsStatic) + if (HasExplicitFieldOffsetLayout() && !fIsStatic) IfFailThrow(pFD->SetOffset(pLayoutFieldInfo->m_placement.m_offset)); - else if (IsManagedSequential() && !fIsStatic) + else if (LayoutContainsNoGCPointers() && !fIsStatic) IfFailThrow(pFD->SetOffset(pLayoutFieldInfo->m_placement.m_offset)); else if (bCurrentFieldIsGCPointer) pFD->SetOffset(FIELD_OFFSET_UNPLACED_GC_PTR); @@ -8329,8 +8316,10 @@ MethodTableBuilder::HandleExplicitLayout( UINT instanceSliceSize = 0; DWORD firstObjectOverlapOffset = ((DWORD)(-1)); + UINT instanceSliceAlignment = (bmtGCSeries->numSeries != 0 ? TARGET_POINTER_SIZE : 1); UINT i; + UINT valueClassCacheIndex = (UINT)-1; for (i = 0; i < bmtMetaData->cFields; i++) { FieldDesc *pFD = bmtMFDescs->ppFieldDescList[i]; @@ -8339,8 +8328,30 @@ MethodTableBuilder::HandleExplicitLayout( continue; } + ++valueClassCacheIndex; + + UINT32 fieldSize; + UINT32 fieldAlignment; + CorElementType fieldCorElemType = pFD->GetFieldType(); + if (!EEClassLayoutInfo::TryGetPrimitiveFieldSizeAndAlignment(fieldCorElemType, &fieldSize, &fieldAlignment)) + { + if (fieldCorElemType == ELEMENT_TYPE_VALUETYPE) + { + MethodTable *pByValueMT = pByValueClassCache[valueClassCacheIndex]; + UINT32 instanceFieldBytes = pByValueMT->GetNumInstanceFieldBytes(); + fieldSize = instanceFieldBytes; + fieldAlignment = TARGET_POINTER_SIZE; +#ifdef FEATURE_64BIT_ALIGNMENT + if (pByValueMT->RequiresAlign8()) + { + fieldAlignment = 8; + } +#endif // FEATURE_64BIT_ALIGNMENT + } + } + UINT fieldExtent = 0; - if (!ClrSafeInt::addition(pFD->GetOffset_NoLogging(), GetFieldSize(pFD), fieldExtent)) + if (!ClrSafeInt::addition(pFD->GetOffset_NoLogging(), fieldSize, fieldExtent)) { BuildMethodTableThrowException(COR_E_OVERFLOW); } @@ -8349,6 +8360,11 @@ MethodTableBuilder::HandleExplicitLayout( { instanceSliceSize = fieldExtent; } + + if (fieldAlignment > instanceSliceAlignment) + { + instanceSliceAlignment = fieldAlignment; + } } CQuickBytes qb; @@ -8381,7 +8397,7 @@ MethodTableBuilder::HandleExplicitLayout( ExplicitClassTrust explicitClassTrust; - UINT valueClassCacheIndex = ((UINT)(-1)); + valueClassCacheIndex = ((UINT)(-1)); UINT badOffset = 0; FieldDesc * pFD = NULL; for (i = 0; i < bmtMetaData->cFields; i++) @@ -8560,15 +8576,6 @@ MethodTableBuilder::HandleExplicitLayout( SetHasOverLayedFields(); } - if (IsBlittable() || IsManagedSequential()) - { - // Bug 849333: We shouldn't update "bmtFP->NumInstanceFieldBytes" - // for Blittable/ManagedSequential types. As this will break backward compatiblity - // for the size of types that return true for HasExplicitFieldOffsetLayout() - // - return; - } - FindPointerSeriesExplicit(instanceSliceSize, pFieldLayout); // Fixup the offset to include parent as current offsets are relative to instance slice @@ -8577,16 +8584,20 @@ MethodTableBuilder::HandleExplicitLayout( // Instance fields start right after the parent S_UINT32 dwInstanceSliceOffset = S_UINT32(HasParent() ? GetParentMethodTable()->GetNumInstanceFieldBytes() : 0); - if (bmtGCSeries->numSeries != 0) - { - dwInstanceSliceOffset.AlignUp(TARGET_POINTER_SIZE); - } + +#if !defined(TARGET_64BIT) && !defined(FEATURE_64BIT_ALIGNMENT) + instanceSliceAlignment = min(instanceSliceAlignment, TARGET_POINTER_SIZE); +#endif + + dwInstanceSliceOffset.AlignUp(instanceSliceAlignment); if (dwInstanceSliceOffset.IsOverflow()) { // addition overflow or cast truncation BuildMethodTableThrowException(IDS_CLASSLOAD_GENERAL); } + S_UINT32 numInstanceFieldBytesUnaligned = dwInstanceSliceOffset + S_UINT32(instanceSliceSize); + instanceSliceSize = ALIGN_UP(instanceSliceSize, instanceSliceAlignment); S_UINT32 numInstanceFieldBytes = dwInstanceSliceOffset + S_UINT32(instanceSliceSize); if (IsValueClass()) @@ -8600,7 +8611,7 @@ MethodTableBuilder::HandleExplicitLayout( if (clstotalsize != 0) { // size must be large enough to accomodate layout. If not, we use the layout size instead. - if (!numInstanceFieldBytes.IsOverflow() && clstotalsize >= numInstanceFieldBytes.Value()) + if (!numInstanceFieldBytesUnaligned.IsOverflow() && clstotalsize >= numInstanceFieldBytesUnaligned.Value()) { numInstanceFieldBytes = S_UINT32(clstotalsize); } diff --git a/src/coreclr/vm/methodtablebuilder.h b/src/coreclr/vm/methodtablebuilder.h index c44568a2f96c3c..bded93a95c72b4 100644 --- a/src/coreclr/vm/methodtablebuilder.h +++ b/src/coreclr/vm/methodtablebuilder.h @@ -226,6 +226,7 @@ class MethodTableBuilder BOOL IsNested() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->IsNested(); } BOOL HasFieldsWhichMustBeInited() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->HasFieldsWhichMustBeInited(); } BOOL IsBlittable() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->IsBlittable(); } + BOOL LayoutContainsNoGCPointers() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->LayoutContainsNoGCPointers(); } PTR_MethodDescChunk GetChunks() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->GetChunks(); } BOOL HasExplicitFieldOffsetLayout() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->HasExplicitFieldOffsetLayout(); } BOOL IsManagedSequential() { WRAPPER_NO_CONTRACT; return GetHalfBakedClass()->IsManagedSequential(); } diff --git a/src/tests/readytorun/crossgen2/Program.cs b/src/tests/readytorun/crossgen2/Program.cs index b0c011e5b94a83..91a6c986310474 100644 --- a/src/tests/readytorun/crossgen2/Program.cs +++ b/src/tests/readytorun/crossgen2/Program.cs @@ -1495,8 +1495,8 @@ private unsafe static bool ExplicitlySizedStructTest() } { - Console.WriteLine($"sizeof(ExplicitlySizedStructSequentialSizeTooSmall) != 0x14 {sizeof(ExplicitlySizedStructSequentialSizeTooSmall)} != 0x14"); - if (sizeof(ExplicitlySizedStructSequentialSizeTooSmall) != 0x14) + Console.WriteLine($"sizeof(ExplicitlySizedStructSequentialSizeTooSmall) != 0x18 {sizeof(ExplicitlySizedStructSequentialSizeTooSmall)} != 0x18"); + if (sizeof(ExplicitlySizedStructSequentialSizeTooSmall) != 0x18) return false; ExplicitlySizedStructSequentialSizeTooSmall str2 = new ExplicitlySizedStructSequentialSizeTooSmall(); @@ -1519,8 +1519,8 @@ private unsafe static bool ExplicitlySizedStructTest() } { - Console.WriteLine($"sizeof(ExplicitlySizedStructExplicitSizeTooSmall) != 0x15 {sizeof(ExplicitlySizedStructExplicitSizeTooSmall)} != 0x15"); - if (sizeof(ExplicitlySizedStructExplicitSizeTooSmall) != 0x15) + Console.WriteLine($"sizeof(ExplicitlySizedStructExplicitSizeTooSmall) != 0x18 {sizeof(ExplicitlySizedStructExplicitSizeTooSmall)} != 0x18"); + if (sizeof(ExplicitlySizedStructExplicitSizeTooSmall) != 0x18) return false; ExplicitlySizedStructExplicitSizeTooSmall str4 = new ExplicitlySizedStructExplicitSizeTooSmall();