// NOTE: Please read this before adding or changing anything in this file. // // This file doesn't contain any actual tests. It only contains structs. // Tests are automatically generated from all structs in this file, // which test: // - the size of the struct // - the offsets of each field // // When a struct contains a pointer, the test needs to use // OverrideOn32BitNative so that wasm tests can compare with the correct // values when testing 32-bit wasm on a 64-bit host platform. // While it would be possible to use Roslyn to calculate these // values automatically, for simplicity we use a couple of // generator-specific attributes to set these manually: // - [TestGeneratorOverride32BitSize(20)] should be set on a struct // - [TestGeneratorOverride32BitOffset(12)] should be set on a field // See the file below for examples. // // The test generation code lives in Burst.Compiler.IL.Tests.CodeGen. // After making changes to this file, please run that project. // // The generated tests are in 050-TestStructsLayout.Generated.cs. using System; using System.Runtime.InteropServices; namespace Burst.Compiler.IL.Tests { partial class TestStructsLayout { [StructLayout(LayoutKind.Explicit, Size = 8)] private unsafe struct CheckHoleInner { [FieldOffset(0)] public byte* m_Ptr; } [TestGeneratorOverride32BitSize(20)] private struct CheckHoleOuter { public CheckHoleInner a; public int b; [TestGeneratorOverride32BitOffset(12)] public CheckHoleInner c; } [StructLayout(LayoutKind.Explicit)] private struct ExplicitStructWithoutSize2 { [FieldOffset(0)] public long a; [FieldOffset(8)] public sbyte b; [FieldOffset(9)] public int c; } [StructLayout(LayoutKind.Explicit)] private struct ExplicitStructWithoutSize { [FieldOffset(0)] public int a; [FieldOffset(4)] public sbyte b; [FieldOffset(5)] public int c; } [StructLayout(LayoutKind.Sequential, Size = 12)] private struct SequentialStructWithSize3 { public int a; public int b; public sbyte c; } [StructLayout(LayoutKind.Sequential)] private struct SequentialStructWithoutSize { public int a; public int b; public sbyte c; } private struct SequentialStructEmptyNoAttributes { } [StructLayout(LayoutKind.Explicit)] private struct ExplicitStructWithEmptySequentialFields { [FieldOffset(0)] public SequentialStructEmptyNoAttributes FieldA; [FieldOffset(0)] public SequentialStructEmptyNoAttributes FieldB; } [StructLayout(LayoutKind.Explicit)] private struct ExplicitStrictWithEmptyAndNonEmptySequentialFields { [FieldOffset(0)] public SequentialStructEmptyNoAttributes FieldA; [FieldOffset(0)] public SequentialStructWithoutSize FieldB; } [StructLayout(LayoutKind.Sequential, Pack = 8)] private struct StructWithPack8 { public int FieldA; public int FieldB; } [StructLayout(LayoutKind.Sequential, Pack = 2)] private struct StructPack2WithBytesAndInt { public byte FieldA; public byte FieldB; public int FieldC; } [StructLayout(LayoutKind.Sequential, Pack = 2)] private struct StructPack2WithBytesAndInts { public byte FieldA; public byte FieldB; public int FieldC; public int FieldD; } [StructLayout(LayoutKind.Sequential, Pack = 1)] private struct StructPack1WithBytesAndInt { public byte FieldA; public byte FieldB; public int FieldC; } [StructLayout(LayoutKind.Sequential, Pack = 1)] private struct StructPack1WithByteAndInt { public byte FieldA; public int FieldB; } private struct StructPack1WithByteAndIntWrapper { public StructPack1WithByteAndInt FieldA; public StructPack1WithByteAndInt FieldB; } private struct StructPack1WithByteAndIntWrapper2 { public StructPack1WithByteAndIntWrapper FieldA; public StructPack1WithByteAndIntWrapper FieldB; } [StructLayout(LayoutKind.Sequential, Size = 12, Pack = 1)] private struct StructWithSizeAndPack { public double FieldA; public int FieldB; } private struct StructWithSizeAndPackWrapper { public byte FieldA; public StructWithSizeAndPack FieldB; } [StructLayout(LayoutKind.Explicit, Size = 12, Pack = 4)] private struct StructWithSizeAndPack4 { [FieldOffset(0)] public double FieldA; [FieldOffset(8)] public int FieldB; } private struct StructWithSizeAndPack4Wrapper { public byte FieldA; public StructWithSizeAndPack4 FieldB; } [StructLayout(LayoutKind.Explicit, Pack = 1)] private struct StructExplicitPack1WithByteAndInt { [FieldOffset(0)] public byte FieldA; [FieldOffset(1)] public int FieldB; } private struct StructExplicitPack1WithByteAndIntWrapper { public StructExplicitPack1WithByteAndInt FieldA; public StructExplicitPack1WithByteAndInt FieldB; } private struct StructExplicitPack1WithByteAndIntWrapper2 { public StructExplicitPack1WithByteAndIntWrapper FieldA; public StructExplicitPack1WithByteAndIntWrapper FieldB; } [StructLayout(LayoutKind.Explicit, Size = 12, Pack = 1)] private struct StructExplicitWithSizeAndPack { [FieldOffset(0)] public double FieldA; [FieldOffset(8)] public int FieldB; } private struct StructExplicitWithSizeAndPackWrapper { public byte FieldA; public StructExplicitWithSizeAndPack FieldB; } [StructLayout(LayoutKind.Explicit, Size = 12, Pack = 4)] private struct StructExplicitWithSizeAndPack4 { [FieldOffset(0)] public double FieldA; [FieldOffset(8)] public int FieldB; } private struct StructExplicitWithSizeAndPack4Wrapper { public byte FieldA; public StructExplicitWithSizeAndPack4 FieldB; } } [AttributeUsage(AttributeTargets.Struct)] internal sealed class TestGeneratorOverride32BitSizeAttribute : Attribute { public readonly int Size; public TestGeneratorOverride32BitSizeAttribute(int size) { Size = size; } } [AttributeUsage(AttributeTargets.Field)] internal sealed class TestGeneratorOverride32BitOffsetAttribute : Attribute { public readonly int Offset; public TestGeneratorOverride32BitOffsetAttribute(int offset) { Offset = offset; } } }