Exemple #1
0
        internal void ComputeInstanceLayout(InstanceLayoutKind layoutKind)
        {
            if (_fieldLayoutFlags.HasFlags(FieldLayoutFlags.ComputedInstanceTypeFieldsLayout | FieldLayoutFlags.ComputedInstanceTypeLayout))
            {
                return;
            }

            var computedLayout = this.Context.GetLayoutAlgorithmForType(this).ComputeInstanceLayout(this, layoutKind);

            _instanceFieldSize          = computedLayout.FieldSize;
            _instanceFieldAlignment     = computedLayout.FieldAlignment;
            _instanceByteCountUnaligned = computedLayout.ByteCountUnaligned;
            _instanceByteAlignment      = computedLayout.ByteCountAlignment;

            if (computedLayout.Offsets != null)
            {
                foreach (var fieldAndOffset in computedLayout.Offsets)
                {
                    Debug.Assert(fieldAndOffset.Field.OwningType == this);
                    fieldAndOffset.Field.InitializeOffset(fieldAndOffset.Offset);
                    _fieldLayoutFlags.AddFlags(FieldLayoutFlags.ComputedInstanceTypeFieldsLayout);
                }
            }

            _fieldLayoutFlags.AddFlags(FieldLayoutFlags.ComputedInstanceTypeLayout);
        }
        public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, InstanceLayoutKind layoutKind)
        {
            if (!type.IsTemplateUniversal() && (layoutKind == InstanceLayoutKind.TypeOnly))
            {
                // Non universal generics can just use the template's layout
                DefType template = (DefType)type.ComputeTemplate();
                return _noMetadataFieldLayoutAlgorithm.ComputeInstanceLayout(template, InstanceLayoutKind.TypeOnly);
            }

            // Only needed for universal generics, or when looking up an offset for a field for a universal generic
            LowLevelList<int> fieldOffsets;
            int[] position = ComputeTypeSizeAndAlignment(type, FieldLoadState.Instance, out fieldOffsets);

            int numInstanceFields = 0;
            foreach (NativeLayoutFieldDesc field in type.NativeLayoutFields)
            {
                if (!field.IsStatic)
                {
                    numInstanceFields++;
                }
            }

            int byteCountAlignment = position[InstanceAlignmentEntry];
            byteCountAlignment = type.Context.Target.GetObjectAlignment(byteCountAlignment);

            ComputedInstanceFieldLayout layout = new ComputedInstanceFieldLayout()
            {
                Offsets = new FieldAndOffset[numInstanceFields],
                ByteCountAlignment = byteCountAlignment,
                ByteCountUnaligned = position[(int)NativeFormat.FieldStorage.Instance],
                PackValue = 0 // TODO, as we add more metadata handling logic, find out if its necessary to use a meaningful value here
            };

            if (!type.IsValueType)
            {
                layout.FieldAlignment = type.Context.Target.PointerSize;
                layout.FieldSize = type.Context.Target.PointerSize;
            }
            else
            {
                layout.FieldAlignment = position[InstanceAlignmentEntry];
                layout.FieldSize = MemoryHelpers.AlignUp(position[(int)NativeFormat.FieldStorage.Instance], layout.FieldAlignment);
            }

            int curInstanceField = 0;
            foreach (NativeLayoutFieldDesc field in type.NativeLayoutFields)
            {
                if (!field.IsStatic)
                {
                    layout.Offsets[curInstanceField] = new FieldAndOffset(field, fieldOffsets[curInstanceField]);
                    curInstanceField++;
                }
            }

            return layout;
        }
        public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defType, InstanceLayoutKind layoutKind)
        {
            MetadataType type = (MetadataType)defType;
            // CLI - Partition 1, section 9.5 - Generic types shall not be marked explicitlayout.  
            if (type.HasInstantiation && type.IsExplicitLayout)
            {
                throw new TypeLoadException();
            }

            // Count the number of instance fields in advance for convenience
            int numInstanceFields = 0;
            foreach (var field in type.GetFields())
                if (!field.IsStatic)
                    numInstanceFields++;

            if (type.IsModuleType)
            {
                // This is a global type, it must not have instance fields.
                if (numInstanceFields > 0)
                {
                    throw new TypeLoadException();
                }

                // Global types do not do the rest of instance field layout.
                ComputedInstanceFieldLayout result = new ComputedInstanceFieldLayout();
                result.PackValue = type.Context.Target.DefaultPackingSize;
                result.Offsets = Array.Empty<FieldAndOffset>();
                return result;
            }

            // CLI - Partition 2, section 22.8
            // A type has layout if it is marked SequentialLayout or ExplicitLayout.  If any type within an inheritance chain has layout, 
            // then so shall all its base classes, up to the one that descends immediately from System.ValueType (if it exists in the type’s 
            // hierarchy); otherwise, from System.Object
            // Note: While the CLI isn't clearly worded, the layout needs to be the same for the entire chain.
            // If the current type isn't ValueType or System.Object and has a layout and the parent type isn't
            // ValueType or System.Object then the layout type attributes need to match
            if ((!type.IsValueType && !type.IsObject) &&
                (type.IsSequentialLayout || type.IsExplicitLayout) &&
                (!type.BaseType.IsValueType && !type.BaseType.IsObject))
            {
                MetadataType baseType = type.MetadataBaseType;

                if (type.IsSequentialLayout != baseType.IsSequentialLayout ||
                    type.IsExplicitLayout != baseType.IsExplicitLayout)
                {
                    throw new TypeLoadException();
                }
            }

            // Enum types must have a single instance field
            if (type.IsEnum && numInstanceFields != 1)
            {
                throw new TypeLoadException();
            }

            if (type.IsPrimitive)
            {
                // Primitive types are special - they may have a single field of the same type
                // as the type itself. They do not do the rest of instance field layout.
                if (numInstanceFields > 1)
                {
                    throw new TypeLoadException();
                }

                SizeAndAlignment instanceByteSizeAndAlignment;
                var sizeAndAlignment = ComputeInstanceSize(
                    type,
                    type.Context.Target.GetWellKnownTypeSize(type),
                    type.Context.Target.GetWellKnownTypeAlignment(type),
                    out instanceByteSizeAndAlignment
                    );

                ComputedInstanceFieldLayout result = new ComputedInstanceFieldLayout
                {
                    ByteCountUnaligned = instanceByteSizeAndAlignment.Size,
                    ByteCountAlignment = instanceByteSizeAndAlignment.Alignment,
                    FieldAlignment = sizeAndAlignment.Alignment,
                    FieldSize = sizeAndAlignment.Size,
                    PackValue = type.Context.Target.DefaultPackingSize
                };

                if (numInstanceFields > 0)
                {
                    FieldDesc instanceField = null;
                    foreach (FieldDesc field in type.GetFields())
                    {
                        if (!field.IsStatic)
                        {
                            Debug.Assert(instanceField == null, "Unexpected extra instance field");
                            instanceField = field;
                        }
                    }

                    Debug.Assert(instanceField != null, "Null instance field");

                    result.Offsets = new FieldAndOffset[] {
                        new FieldAndOffset(instanceField, 0)
                    };
                }
                else
                {
                    result.Offsets = Array.Empty<FieldAndOffset>();
                }

                return result;
            }

            // Verify that no ByRef types present in this type's fields
            foreach (var field in type.GetFields())
                if (field.FieldType is ByRefType)
                    throw new TypeLoadException();

            // If the type has layout, read its packing and size info
            // If the type has explicit layout, also read the field offset info
            if (type.IsExplicitLayout || type.IsSequentialLayout)
            {
                if (type.IsEnum)
                {
                    throw new TypeLoadException();
                }

                var layoutMetadata = type.GetClassLayout();

                // If packing is out of range or not a power of two, throw that the size is invalid
                int packing = layoutMetadata.PackingSize;
                if (packing < 0 || packing > 128 || ((packing & (packing - 1)) != 0))
                {
                    throw new TypeLoadException();
                }

                Debug.Assert(layoutMetadata.Offsets == null || layoutMetadata.Offsets.Length == numInstanceFields);
            }

            // At this point all special cases are handled and all inputs validated

            if (type.IsExplicitLayout)
            {
                return ComputeExplicitFieldLayout(type, numInstanceFields);
            }
            else
            {
                // Treat auto layout as sequential for now
                return ComputeSequentialFieldLayout(type, numInstanceFields);
            }
        }
Exemple #4
0
        public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defType, InstanceLayoutKind layoutKind)
        {
            // Individual field offset layout for a RuntimeDeterminedType is not a supported operation
            if (layoutKind != InstanceLayoutKind.TypeOnly)
            {
                throw new NotSupportedException();
            }

            RuntimeDeterminedType type = (RuntimeDeterminedType)defType;
            DefType canonicalType      = type.CanonicalType;

            ComputedInstanceFieldLayout result = new ComputedInstanceFieldLayout
            {
                ByteCountUnaligned = canonicalType.InstanceByteCountUnaligned,
                ByteCountAlignment = canonicalType.InstanceByteAlignment,
                FieldAlignment     = canonicalType.InstanceFieldAlignment,
                FieldSize          = canonicalType.InstanceFieldSize,
                Offsets            = Array.Empty <FieldAndOffset>(),
                LayoutAbiStable    = canonicalType.LayoutAbiStable
            };

            return(result);
        }
Exemple #5
0
        public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defType, InstanceLayoutKind layoutKind)
        {
            Debug.Assert(IsVectorType(defType));

            LayoutInt alignment;

            string name = defType.Name;

            if (name == "Vector64`1")
            {
                alignment = new LayoutInt(8);
            }
            else if (name == "Vector128`1")
            {
                if (defType.Context.Target.Architecture == TargetArchitecture.ARM)
                {
                    // The Procedure Call Standard for ARM defaults to 8-byte alignment for __m128
                    alignment = new LayoutInt(8);
                }
                else
                {
                    alignment = new LayoutInt(16);
                }
            }
            else
            {
                Debug.Assert(name == "Vector256`1");

                if (defType.Context.Target.Architecture == TargetArchitecture.ARM)
                {
                    // No such type exists for the Procedure Call Standard for ARM. We will default
                    // to the same alignment as __m128, which is supported by the ABI.
                    alignment = new LayoutInt(8);
                }
                else if (defType.Context.Target.Architecture == TargetArchitecture.ARM64)
                {
                    // The Procedure Call Standard for ARM 64-bit (with SVE support) defaults to
                    // 16-byte alignment for __m256.
                    alignment = new LayoutInt(16);
                }
                else
                {
                    alignment = new LayoutInt(32);
                }
            }

            ComputedInstanceFieldLayout layoutFromMetadata = _fallbackAlgorithm.ComputeInstanceLayout(defType, layoutKind);

            return(new ComputedInstanceFieldLayout
            {
                ByteCountUnaligned = layoutFromMetadata.ByteCountUnaligned,
                ByteCountAlignment = layoutFromMetadata.ByteCountAlignment,
                FieldAlignment = alignment,
                FieldSize = layoutFromMetadata.FieldSize,
                Offsets = layoutFromMetadata.Offsets,
            });
        }
Exemple #6
0
        public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, InstanceLayoutKind layoutKind)
        {
            if (!type.IsTemplateUniversal() && (layoutKind == InstanceLayoutKind.TypeOnly))
            {
                // Non universal generics can just use the template's layout
                DefType template = (DefType)type.ComputeTemplate();
                return(_noMetadataFieldLayoutAlgorithm.ComputeInstanceLayout(template, InstanceLayoutKind.TypeOnly));
            }

            // Only needed for universal generics, or when looking up an offset for a field for a universal generic
            LowLevelList <LayoutInt> fieldOffsets;

            LayoutInt[] position = ComputeTypeSizeAndAlignment(type, FieldLoadState.Instance, out fieldOffsets);

            int numInstanceFields = 0;

            foreach (NativeLayoutFieldDesc field in type.NativeLayoutFields)
            {
                if (!field.IsStatic)
                {
                    numInstanceFields++;
                }
            }

            LayoutInt byteCountAlignment = position[InstanceAlignmentEntry];

            byteCountAlignment = type.Context.Target.GetObjectAlignment(byteCountAlignment);

            ComputedInstanceFieldLayout layout = new ComputedInstanceFieldLayout()
            {
                Offsets            = new FieldAndOffset[numInstanceFields],
                ByteCountAlignment = byteCountAlignment,
                ByteCountUnaligned = position[(int)NativeFormat.FieldStorage.Instance],
            };

            if (!type.IsValueType)
            {
                layout.FieldAlignment = type.Context.Target.LayoutPointerSize;
                layout.FieldSize      = type.Context.Target.LayoutPointerSize;
            }
            else
            {
                layout.FieldAlignment = position[InstanceAlignmentEntry];
                layout.FieldSize      = LayoutInt.AlignUp(position[(int)NativeFormat.FieldStorage.Instance], layout.FieldAlignment);
            }

            int curInstanceField = 0;

            foreach (NativeLayoutFieldDesc field in type.NativeLayoutFields)
            {
                if (!field.IsStatic)
                {
                    layout.Offsets[curInstanceField] = new FieldAndOffset(field, fieldOffsets[curInstanceField]);
                    curInstanceField++;
                }
            }

            return(layout);
        }
Exemple #7
0
        public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defType, InstanceLayoutKind layoutKind)
        {
            Debug.Assert(IsIntegerType(defType));

            string name = defType.Name;

            Debug.Assert((name == "Int128") || (name == "UInt128"));

            ComputedInstanceFieldLayout layoutFromMetadata = _fallbackAlgorithm.ComputeInstanceLayout(defType, layoutKind);

            if (defType.Context.Target.IsWindows || (defType.Context.Target.PointerSize == 4))
            {
                return(layoutFromMetadata);
            }

            // 64-bit Unix systems follow the System V ABI and have a 16-byte packing requirement for Int128/UInt128

            return(new ComputedInstanceFieldLayout
            {
                ByteCountUnaligned = layoutFromMetadata.ByteCountUnaligned,
                ByteCountAlignment = layoutFromMetadata.ByteCountAlignment,
                FieldAlignment = new LayoutInt(16),
                FieldSize = layoutFromMetadata.FieldSize,
                Offsets = layoutFromMetadata.Offsets,
                LayoutAbiStable = true
            });
        }
Exemple #8
0
        public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, InstanceLayoutKind layoutKind)
        {
            DefType similarSpecifiedVector = GetSimilarVector(type);

            if (similarSpecifiedVector == null)
            {
                List <FieldAndOffset> fieldsAndOffsets = new List <FieldAndOffset>();
                foreach (FieldDesc field in type.GetFields())
                {
                    if (!field.IsStatic)
                    {
                        fieldsAndOffsets.Add(new FieldAndOffset(field, LayoutInt.Indeterminate));
                    }
                }
                ComputedInstanceFieldLayout instanceLayout = new ComputedInstanceFieldLayout()
                {
                    FieldSize          = LayoutInt.Indeterminate,
                    FieldAlignment     = LayoutInt.Indeterminate,
                    ByteCountUnaligned = LayoutInt.Indeterminate,
                    ByteCountAlignment = LayoutInt.Indeterminate,
                    Offsets            = fieldsAndOffsets.ToArray(),
                    LayoutAbiStable    = false,
                };
                return(instanceLayout);
            }
            else
            {
                ComputedInstanceFieldLayout layoutFromMetadata = _fallbackAlgorithm.ComputeInstanceLayout(type, layoutKind);
                ComputedInstanceFieldLayout layoutFromSimilarIntrinsicVector = _vectorFallbackAlgorithm.ComputeInstanceLayout(similarSpecifiedVector, layoutKind);

                // TODO, enable this code when we switch Vector<T> to follow the same calling convention as its matching similar intrinsic vector
#if MATCHING_HARDWARE_VECTOR
                return(new ComputedInstanceFieldLayout
                {
                    ByteCountUnaligned = layoutFromSimilarIntrinsicVector.ByteCountUnaligned,
                    ByteCountAlignment = layoutFromSimilarIntrinsicVector.ByteCountAlignment,
                    FieldAlignment = layoutFromSimilarIntrinsicVector.FieldAlignment,
                    FieldSize = layoutFromSimilarIntrinsicVector.FieldSize,
                    Offsets = layoutFromMetadata.Offsets,
                    LayoutAbiStable = _vectorAbiIsStable,
                });
#else
                return(new ComputedInstanceFieldLayout
                {
                    ByteCountUnaligned = layoutFromSimilarIntrinsicVector.ByteCountUnaligned,
                    ByteCountAlignment = layoutFromMetadata.ByteCountAlignment,
                    FieldAlignment = layoutFromMetadata.FieldAlignment,
                    FieldSize = layoutFromSimilarIntrinsicVector.FieldSize,
                    Offsets = layoutFromMetadata.Offsets,
                    LayoutAbiStable = _vectorAbiIsStable,
                });
#endif
            }
        }
 public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, InstanceLayoutKind layoutKind)
 {
     return(new ComputedInstanceFieldLayout()
     {
         FieldSize = LayoutInt.Indeterminate,
         FieldAlignment = LayoutInt.Indeterminate,
         ByteCountUnaligned = LayoutInt.Indeterminate,
         ByteCountAlignment = LayoutInt.Indeterminate,
         Offsets = Array.Empty <FieldAndOffset>()
     });
 }
Exemple #10
0
        public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defType, InstanceLayoutKind layoutKind)
        {
            TargetDetails targetDetails = defType.Context.Target;
            ComputedInstanceFieldLayout layoutFromMetadata = _fallbackAlgorithm.ComputeInstanceLayout(defType, layoutKind);

            // System.Object has an EEType field in the standard AOT version used in this repo.
            // Make sure that we always use the CoreCLR version which (currently) has no fields.
            Debug.Assert(0 == layoutFromMetadata.Offsets.Length, "Incompatible system library. The CoreCLR System.Private.CoreLib must be used when compiling in ready-to-run mode.");

            return(new ComputedInstanceFieldLayout
            {
                ByteCountUnaligned = targetDetails.LayoutPointerSize,
                ByteCountAlignment = targetDetails.LayoutPointerSize,
                FieldAlignment = layoutFromMetadata.FieldAlignment,
                FieldSize = layoutFromMetadata.FieldSize,
                Offsets = layoutFromMetadata.Offsets,
            });
        }
 public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, InstanceLayoutKind layoutKind)
 {
     return(new ComputedInstanceFieldLayout()
     {
         PackValue = type.Context.Target.DefaultPackingSize,
         FieldSize = LayoutInt.Indeterminate,
         FieldAlignment = LayoutInt.Indeterminate,
         ByteCountUnaligned = LayoutInt.Indeterminate,
         ByteCountAlignment = LayoutInt.Indeterminate,
         Offsets = Array.Empty <FieldAndOffset>()
     });
 }
 /// <summary>
 /// Compute the instance field layout for a DefType. Must not depend on static field layout for any other type.
 /// </summary>
 public abstract ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, InstanceLayoutKind layoutKind);
        /// <summary>
        /// Reads the minimal information about type layout encoded in the
        /// MethodTable. That doesn't include field information.
        /// </summary>
        public unsafe override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, InstanceLayoutKind layoutKind)
        {
            // If we need the field information, delegate to the native layout algorithm or metadata algorithm
            if (layoutKind != InstanceLayoutKind.TypeOnly)
            {
                if (type.HasNativeLayout)
                {
                    return(s_nativeLayoutFieldAlgorithm.ComputeInstanceLayout(type, layoutKind));
                }
                else
                {
#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
                    return(_metadataFieldLayoutAlgorithm.ComputeInstanceLayout(type, layoutKind));
#else
                    Debug.Assert(false);
                    return(default);
        internal void ComputeInstanceLayout(InstanceLayoutKind layoutKind)
        {
            if (_fieldLayoutFlags.HasFlags(FieldLayoutFlags.ComputedInstanceTypeFieldsLayout | FieldLayoutFlags.ComputedInstanceTypeLayout))
                return;

            var computedLayout = this.Context.GetLayoutAlgorithmForType(this).ComputeInstanceLayout(this, layoutKind);

            _instanceFieldSize = computedLayout.FieldSize;
            _instanceFieldAlignment = computedLayout.FieldAlignment;
            _instanceByteCountUnaligned = computedLayout.ByteCountUnaligned;
            _instanceByteAlignment = computedLayout.ByteCountAlignment;

            if (computedLayout.Offsets != null)
            {
                foreach (var fieldAndOffset in computedLayout.Offsets)
                {
                    Debug.Assert(fieldAndOffset.Field.OwningType == this);
                    fieldAndOffset.Field.InitializeOffset(fieldAndOffset.Offset);
                    _fieldLayoutFlags.AddFlags(FieldLayoutFlags.ComputedInstanceTypeFieldsLayout);
                }
            }

            _fieldLayoutFlags.AddFlags(FieldLayoutFlags.ComputedInstanceTypeLayout);
        }
        /// <summary>
        /// Reads the minimal information about type layout encoded in the
        /// EEType. That doesn't include field information.
        /// </summary>
        public unsafe override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, InstanceLayoutKind layoutKind)
        {
            // If we need the field information, delegate to the native layout algorithm or metadata algorithm
            if (layoutKind != InstanceLayoutKind.TypeOnly)
            {
                if (type.HasNativeLayout)
                {
                    return(s_nativeLayoutFieldAlgorithm.ComputeInstanceLayout(type, layoutKind));
                }
                else
                {
                    return(_metadataFieldLayoutAlgorithm.ComputeInstanceLayout(type, layoutKind));
                }
            }

            type.RetrieveRuntimeTypeHandleIfPossible();
            Debug.Assert(!type.RuntimeTypeHandle.IsNull());
            EEType *eeType = type.RuntimeTypeHandle.ToEETypePtr();

            ComputedInstanceFieldLayout layout = new ComputedInstanceFieldLayout()
            {
                ByteCountAlignment = new LayoutInt(IntPtr.Size),
                ByteCountUnaligned = new LayoutInt(eeType->IsInterface ? IntPtr.Size : checked ((int)eeType->FieldByteCountNonGCAligned)),
                FieldAlignment     = new LayoutInt(eeType->FieldAlignmentRequirement),
                Offsets            = (layoutKind == InstanceLayoutKind.TypeOnly) ? null : Array.Empty <FieldAndOffset>(), // No fields in EETypes
                PackValue          = 0,                                                                                   // This isn't explicitly encoded, though FieldSize should take it into account
                // TODO, as we add more metadata handling logic, find out if its necessary.
            };

            if (eeType->IsValueType)
            {
                int valueTypeSize = checked ((int)eeType->ValueTypeSize);
                layout.FieldSize = new LayoutInt(valueTypeSize);
            }
            else
            {
                layout.FieldSize = new LayoutInt(IntPtr.Size);
            }

            if ((eeType->RareFlags & EETypeRareFlags.RequiresAlign8Flag) == EETypeRareFlags.RequiresAlign8Flag)
            {
                layout.ByteCountAlignment = new LayoutInt(8);
            }

            return(layout);
        }
            public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, InstanceLayoutKind layoutKind)
            {
                List <FieldAndOffset> fieldsAndOffsets = new List <FieldAndOffset>();

                foreach (FieldDesc field in type.GetFields())
                {
                    if (!field.IsStatic)
                    {
                        fieldsAndOffsets.Add(new FieldAndOffset(field, LayoutInt.Indeterminate));
                    }
                }
                ComputedInstanceFieldLayout instanceLayout = new ComputedInstanceFieldLayout()
                {
                    FieldSize          = LayoutInt.Indeterminate,
                    FieldAlignment     = LayoutInt.Indeterminate,
                    ByteCountUnaligned = LayoutInt.Indeterminate,
                    ByteCountAlignment = LayoutInt.Indeterminate,
                    Offsets            = fieldsAndOffsets.ToArray(),
                };

                return(instanceLayout);
            }
 /// <summary>
 /// Compute the instance field layout for a DefType. Must not depend on static field layout for any other type.
 /// </summary>
 public abstract ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, InstanceLayoutKind layoutKind);
        public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defType, InstanceLayoutKind layoutKind)
        {
            TargetDetails targetDetails = defType.Context.Target;

            ComputedInstanceFieldLayout layoutFromMetadata = _fallbackAlgorithm.ComputeInstanceLayout(defType, layoutKind);

            LayoutInt instanceFieldSize;

            if (targetDetails.MaximumSimdVectorLength == SimdVectorLength.Vector128Bit)
            {
                instanceFieldSize = new LayoutInt(16);
            }
            else if (targetDetails.MaximumSimdVectorLength == SimdVectorLength.Vector256Bit)
            {
                instanceFieldSize = new LayoutInt(32);
            }
            else
            {
                Debug.Assert(targetDetails.MaximumSimdVectorLength == SimdVectorLength.None);
                return(layoutFromMetadata);
            }

            return(new ComputedInstanceFieldLayout
            {
                ByteCountUnaligned = instanceFieldSize,
                ByteCountAlignment = layoutFromMetadata.ByteCountAlignment,
                FieldAlignment = layoutFromMetadata.FieldAlignment,
                FieldSize = instanceFieldSize,
                Offsets = layoutFromMetadata.Offsets,
            });
        }
        public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defType, InstanceLayoutKind layoutKind)
        {
            MetadataType type = (MetadataType)defType;

            if (type.IsGenericDefinition)
            {
                ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type);
            }

            // CLI - Partition 1, section 9.5 - Generic types shall not be marked explicitlayout.
            if (type.HasInstantiation && type.IsExplicitLayout)
            {
                ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadExplicitGeneric, type.GetTypeDefinition());
            }

            // Count the number of instance fields in advance for convenience
            int numInstanceFields = 0;

            foreach (var field in type.GetFields())
            {
                if (field.IsStatic)
                {
                    continue;
                }

                TypeDesc fieldType = field.FieldType;

                // ByRef instance fields are not allowed.
                if (fieldType.IsByRef)
                {
                    ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type);
                }

                // ByRef-like instance fields on non-byref-like types are not allowed.
                if (fieldType.IsByRefLike && !type.IsByRefLike)
                {
                    ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type);
                }

                numInstanceFields++;
            }

            if (type.IsModuleType)
            {
                // This is a global type, it must not have instance fields.
                if (numInstanceFields > 0)
                {
                    ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type);
                }

                // Global types do not do the rest of instance field layout.
                ComputedInstanceFieldLayout result = new ComputedInstanceFieldLayout();
                result.Offsets = Array.Empty <FieldAndOffset>();
                return(result);
            }

            // CLI - Partition 2, section 22.8
            // A type has layout if it is marked SequentialLayout or ExplicitLayout.  If any type within an inheritance chain has layout,
            // then so shall all its base classes, up to the one that descends immediately from System.ValueType (if it exists in the type's
            // hierarchy); otherwise, from System.Object
            // Note: While the CLI isn't clearly worded, the layout needs to be the same for the entire chain.
            // If the current type isn't ValueType or System.Object and has a layout and the parent type isn't
            // ValueType or System.Object then the layout type attributes need to match
            if ((!type.IsValueType && !type.IsObject) &&
                (type.IsSequentialLayout || type.IsExplicitLayout) &&
                (!type.BaseType.IsValueType && !type.BaseType.IsObject))
            {
                MetadataType baseType = type.MetadataBaseType;

                if (type.IsSequentialLayout != baseType.IsSequentialLayout ||
                    type.IsExplicitLayout != baseType.IsExplicitLayout)
                {
                    ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadBadFormat, type);
                }
            }

            // Enum types must have a single instance field
            if (type.IsEnum && numInstanceFields != 1)
            {
                ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type);
            }

            if (type.IsPrimitive)
            {
                // Primitive types are special - they may have a single field of the same type
                // as the type itself. They do not do the rest of instance field layout.
                if (numInstanceFields > 1)
                {
                    ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type);
                }

                SizeAndAlignment instanceByteSizeAndAlignment;
                var sizeAndAlignment = ComputeInstanceSize(
                    type,
                    type.Context.Target.GetWellKnownTypeSize(type),
                    type.Context.Target.GetWellKnownTypeAlignment(type),
                    0,
                    out instanceByteSizeAndAlignment
                    );

                ComputedInstanceFieldLayout result = new ComputedInstanceFieldLayout
                {
                    ByteCountUnaligned = instanceByteSizeAndAlignment.Size,
                    ByteCountAlignment = instanceByteSizeAndAlignment.Alignment,
                    FieldAlignment     = sizeAndAlignment.Alignment,
                    FieldSize          = sizeAndAlignment.Size,
                };

                if (numInstanceFields > 0)
                {
                    FieldDesc instanceField = null;
                    foreach (FieldDesc field in type.GetFields())
                    {
                        if (!field.IsStatic)
                        {
                            Debug.Assert(instanceField == null, "Unexpected extra instance field");
                            instanceField = field;
                        }
                    }

                    Debug.Assert(instanceField != null, "Null instance field");

                    result.Offsets = new FieldAndOffset[] {
                        new FieldAndOffset(instanceField, LayoutInt.Zero)
                    };
                }
                else
                {
                    result.Offsets = Array.Empty <FieldAndOffset>();
                }

                return(result);
            }

            // If the type has layout, read its packing and size info
            // If the type has explicit layout, also read the field offset info
            if (type.IsExplicitLayout || type.IsSequentialLayout)
            {
                if (type.IsEnum)
                {
                    ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadBadFormat, type);
                }

                var layoutMetadata = type.GetClassLayout();

                // If packing is out of range or not a power of two, throw that the size is invalid
                int packing = layoutMetadata.PackingSize;
                if (packing < 0 || packing > 128 || ((packing & (packing - 1)) != 0))
                {
                    ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadBadFormat, type);
                }

                Debug.Assert(layoutMetadata.Offsets == null || layoutMetadata.Offsets.Length == numInstanceFields);
            }

            // At this point all special cases are handled and all inputs validated
            return(ComputeInstanceFieldLayout(type, numInstanceFields));
        }
Exemple #20
0
        public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defType, InstanceLayoutKind layoutKind)
        {
            Debug.Assert(IsIntegerType(defType));

            string name = defType.Name;

            Debug.Assert((name == "Int128") || (name == "UInt128"));

            ComputedInstanceFieldLayout layoutFromMetadata = _fallbackAlgorithm.ComputeInstanceLayout(defType, layoutKind);

            // 32bit platforms use standard metadata layout engine
            if (defType.Context.Target.Architecture == TargetArchitecture.ARM)
            {
                layoutFromMetadata.LayoutAbiStable           = false; // Int128 parameter passing ABI is unstable at this time
                layoutFromMetadata.IsInt128OrHasInt128Fields = true;
                return(layoutFromMetadata);
            }

            // 64-bit Unix systems follow the System V ABI and have a 16-byte packing requirement for Int128/UInt128

            return(new ComputedInstanceFieldLayout
            {
                ByteCountUnaligned = layoutFromMetadata.ByteCountUnaligned,
                ByteCountAlignment = layoutFromMetadata.ByteCountAlignment,
                FieldAlignment = new LayoutInt(16),
                FieldSize = layoutFromMetadata.FieldSize,
                Offsets = layoutFromMetadata.Offsets,
                LayoutAbiStable = false, // Int128 parameter passing ABI is unstable at this time
                IsInt128OrHasInt128Fields = true
            });
        }