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); } }
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); }
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, }); }
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); }
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 }); }
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>() }); }
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); }
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)); }
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 }); }