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 unsafe override bool ComputeContainsGCPointers(DefType type) { if (type.IsTemplateCanonical()) { return type.ComputeTemplate().RuntimeTypeHandle.ToEETypePtr()->HasGCPointers; } else { if (type.RetrieveRuntimeTypeHandleIfPossible()) { return type.RuntimeTypeHandle.ToEETypePtr()->HasGCPointers; } return type.GetOrCreateTypeBuilderState().InstanceGCLayout != null; } }
private static void EnsureFieldLayoutLoadedForNonUniversalType(DefType type) { Debug.Assert(type.HasInstantiation); Debug.Assert(!type.ComputeTemplate().IsCanonicalSubtype(CanonicalFormKind.Universal)); if (type.NativeLayoutFields != null) return; // Look up the universal template for this type. Only the universal template has field layout // information, so we have to use it to parse the field layout. NativeLayoutInfoLoadContext universalLayoutLoadContext; NativeParser typeInfoParser = type.GetOrCreateTypeBuilderState().GetParserForUniversalNativeLayoutInfo(out universalLayoutLoadContext); if (typeInfoParser.IsNull) throw new TypeBuilder.MissingTemplateException(); // Now parse that layout into the NativeLayoutFields array. NativeParser fieldLayoutParser = typeInfoParser.GetParserForBagElementKind(BagElementKind.FieldLayout); type.NativeLayoutFields = ParseFieldLayout(type, universalLayoutLoadContext, fieldLayoutParser); }
private static void EnsureFieldLayoutLoadedForUniversalType(DefType type, NativeLayoutInfoLoadContext loadContext, NativeParser fieldLayoutParser) { Debug.Assert(type.HasInstantiation); Debug.Assert(type.ComputeTemplate().IsCanonicalSubtype(CanonicalFormKind.Universal)); if (type.NativeLayoutFields != null) return; type.NativeLayoutFields = ParseFieldLayout(type, loadContext, fieldLayoutParser); }