File: Compiler\CompilerMetadataFieldLayoutAlgorithm.cs
Web Access
Project: src\src\runtime\src\coreclr\tools\aot\ILCompiler.Compiler\ILCompiler.Compiler.csproj (ILCompiler.Compiler)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Internal.TypeSystem;

using Debug = System.Diagnostics.Debug;

namespace ILCompiler
{
    internal sealed class CompilerMetadataFieldLayoutAlgorithm : MetadataFieldLayoutAlgorithm
    {
        // GC statics start with a pointer to the "MethodTable" that signals the size and GCDesc to the GC
        public static LayoutInt GetGCStaticFieldOffset(TypeSystemContext context) => context.Target.LayoutPointerSize;

        protected override void PrepareRuntimeSpecificStaticFieldLayout(TypeSystemContext context, ref ComputedStaticFieldLayout layout)
        {
            LayoutInt offset = GetGCStaticFieldOffset(context);
            layout.GcStatics.Size = offset;
            layout.ThreadGcStatics.Size = offset;
        }

        protected override void FinalizeRuntimeSpecificStaticFieldLayout(TypeSystemContext context, ref ComputedStaticFieldLayout layout)
        {
            LayoutInt offset = GetGCStaticFieldOffset(context);

            // If the size of GCStatics is equal to the size set in PrepareRuntimeSpecificStaticFieldLayout, we
            // don't have any GC statics
            if (layout.GcStatics.Size == offset)
            {
                layout.GcStatics.Size = LayoutInt.Zero;
            }
            if (layout.ThreadGcStatics.Size == offset)
            {
                layout.ThreadGcStatics.Size = LayoutInt.Zero;
            }

            // NativeAOT makes no distinction between Gc / non-Gc thread statics. All are placed into ThreadGcStatics since thread statics
            // are typically rare.
            Debug.Assert(layout.ThreadNonGcStatics.Size == LayoutInt.Zero);
        }

        protected override ComputedInstanceFieldLayout ComputeInstanceFieldLayout(MetadataType type, int numInstanceFields)
        {
            ClassLayoutMetadata layoutMetadata = type.GetClassLayout();
            return layoutMetadata.Kind switch
            {
                MetadataLayoutKind.Explicit => ComputeExplicitFieldLayout(type, numInstanceFields, layoutMetadata),
                // Sequential layout has to be respected for blittable types only. We use approximation and respect it for
                // all types without GC references (ie C# unmanaged types).
                MetadataLayoutKind.Sequential when !type.ContainsGCPointers => ComputeSequentialFieldLayout(type, numInstanceFields, layoutMetadata),
                MetadataLayoutKind.CStruct => ComputeCStructFieldLayout(type, numInstanceFields),
                MetadataLayoutKind.CUnion => ComputeCUnionFieldLayout(type, numInstanceFields),
                _ => ComputeAutoFieldLayout(type, numInstanceFields, layoutMetadata),
            };
        }
    }
}