public override ComputedStaticFieldLayout ComputeStaticFieldLayout(DefType defType, StaticLayoutKind layoutKind) { MetadataType type = (MetadataType)defType; int numStaticFields = 0; foreach (var field in type.GetFields()) { if (!field.IsStatic || field.HasRva || field.IsLiteral) { continue; } numStaticFields++; } ComputedStaticFieldLayout result; result.GcStatics = new StaticsBlock(); result.NonGcStatics = new StaticsBlock(); result.ThreadGcStatics = new StaticsBlock(); result.ThreadNonGcStatics = new StaticsBlock(); if (numStaticFields == 0) { result.Offsets = Array.Empty <FieldAndOffset>(); return(result); } result.Offsets = new FieldAndOffset[numStaticFields]; PrepareRuntimeSpecificStaticFieldLayout(type.Context, ref result); int index = 0; foreach (var field in type.GetFields()) { // Nonstatic fields, literal fields, and RVA mapped fields don't participate in layout if (!field.IsStatic || field.HasRva || field.IsLiteral) { continue; } TypeDesc fieldType = field.FieldType; if (fieldType.IsByRef || (fieldType.IsValueType && ((DefType)fieldType).IsByRefLike)) { ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } ref StaticsBlock block = ref GetStaticsBlockForField(ref result, field); SizeAndAlignment sizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, type.Context.Target.DefaultPackingSize); block.Size = LayoutInt.AlignUp(block.Size, sizeAndAlignment.Alignment); result.Offsets[index] = new FieldAndOffset(field, block.Size); block.Size = block.Size + sizeAndAlignment.Size; block.LargestAlignment = LayoutInt.Max(block.LargestAlignment, sizeAndAlignment.Alignment); index++; }
public override IEnumerable <FieldDesc> GetFields() { foreach (var fieldDef in _typeDef.GetFields()) { yield return(_typeDef.Context.GetFieldForInstantiatedType(fieldDef, this)); } }
private void MarkORefLocations(MetadataType type, bool[] orefMap, int offset) { // Recurse into struct fields foreach (FieldDesc field in type.GetFields()) { if (!field.IsStatic) { int fieldOffset = offset + field.Offset.AsInt; if (field.FieldType.IsGCPointer) { for (int index = 0; index < _pointerSize; index++) { orefMap[fieldOffset + index] = true; } } else if (field.FieldType.IsValueType) { MetadataType mdFieldType = (MetadataType)field.FieldType; if (mdFieldType.ContainsGCPointers) { MarkORefLocations(mdFieldType, orefMap, fieldOffset); } } } } }
private void MarkByRefAndORefLocations(MetadataType type, List <FieldLayoutInterval> refMap, int offset) { // Recurse into struct fields foreach (FieldDesc field in type.GetFields()) { if (!field.IsStatic) { int fieldOffset = offset + field.Offset.AsInt; if (field.FieldType.IsGCPointer) { SetFieldLayout(refMap, offset, _pointerSize, FieldLayoutTag.ORef); } else if (field.FieldType.IsByRef || field.FieldType.IsByReferenceOfT) { SetFieldLayout(refMap, offset, _pointerSize, FieldLayoutTag.ByRef); } else if (field.FieldType.IsValueType) { MetadataType mdFieldType = (MetadataType)field.FieldType; if (mdFieldType.ContainsGCPointers || mdFieldType.IsByRefLike) { MarkByRefAndORefLocations(mdFieldType, refMap, fieldOffset); } } } } }
private static ComputedInstanceFieldLayout ComputeSequentialFieldLayout(MetadataType type, int numInstanceFields) { var offsets = new FieldAndOffset[numInstanceFields]; // For types inheriting from another type, field offsets continue on from where they left off int cumulativeInstanceFieldPos = ComputeBytesUsedInParentType(type); int largestAlignmentRequirement = 1; int fieldOrdinal = 0; int packingSize = ComputePackingSize(type); foreach (var field in type.GetFields()) { if (field.IsStatic) { continue; } var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType, packingSize); if (fieldSizeAndAlignment.Alignment > largestAlignmentRequirement) { largestAlignmentRequirement = fieldSizeAndAlignment.Alignment; } cumulativeInstanceFieldPos = AlignmentHelper.AlignUp(cumulativeInstanceFieldPos, fieldSizeAndAlignment.Alignment); offsets[fieldOrdinal] = new FieldAndOffset(field, cumulativeInstanceFieldPos); cumulativeInstanceFieldPos = checked (cumulativeInstanceFieldPos + fieldSizeAndAlignment.Size); fieldOrdinal++; } if (type.IsValueType) { var layoutMetadata = type.GetClassLayout(); cumulativeInstanceFieldPos = Math.Max(cumulativeInstanceFieldPos, layoutMetadata.Size); } SizeAndAlignment instanceByteSizeAndAlignment; var instanceSizeAndAlignment = ComputeInstanceSize(type, cumulativeInstanceFieldPos, largestAlignmentRequirement, out instanceByteSizeAndAlignment); ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout(); computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; computedLayout.FieldSize = instanceSizeAndAlignment.Size; computedLayout.ByteCountUnaligned = instanceByteSizeAndAlignment.Size; computedLayout.ByteCountAlignment = instanceByteSizeAndAlignment.Alignment; computedLayout.Offsets = offsets; return(computedLayout); }
public void TestBlockedAttributes() { // Test that custom attributes referring to blocked types don't show up in metadata var sampleMetadataModule = _context.GetModuleForSimpleName("SampleMetadataAssembly"); Cts.MetadataType attributeHolder = sampleMetadataModule.GetType("BlockedMetadata", "AttributeHolder"); var policy = new SingleFileMetadataPolicy(); var transformResult = MetadataTransform.Run(policy, new[] { _systemModule, sampleMetadataModule }); int blockedCount = 0; int allowedCount = 0; foreach (var field in attributeHolder.GetFields()) { var transformedRecord = transformResult.GetTransformedFieldDefinition(field); Assert.NotNull(transformedRecord); if (field.Name.StartsWith("Blocked")) { blockedCount++; Assert.Equal(0, transformedRecord.CustomAttributes.Count); } else { allowedCount++; Assert.StartsWith("Allowed", field.Name); Assert.Equal(1, transformedRecord.CustomAttributes.Count); } } Assert.Equal(5, allowedCount); Assert.Equal(8, blockedCount); }
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)); }
private static ComputedInstanceFieldLayout ComputeSequentialFieldLayout(MetadataType type, int numInstanceFields) { var offsets = new FieldAndOffset[numInstanceFields]; // For types inheriting from another type, field offsets continue on from where they left off int cumulativeInstanceFieldPos = ComputeBytesUsedInParentType(type); int largestAlignmentRequirement = 1; int fieldOrdinal = 0; int packingSize = ComputePackingSize(type); foreach (var field in type.GetFields()) { if (field.IsStatic) continue; var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType, packingSize); if (fieldSizeAndAlignment.Alignment > largestAlignmentRequirement) largestAlignmentRequirement = fieldSizeAndAlignment.Alignment; cumulativeInstanceFieldPos = AlignmentHelper.AlignUp(cumulativeInstanceFieldPos, fieldSizeAndAlignment.Alignment); offsets[fieldOrdinal] = new FieldAndOffset(field, cumulativeInstanceFieldPos); cumulativeInstanceFieldPos = checked(cumulativeInstanceFieldPos + fieldSizeAndAlignment.Size); fieldOrdinal++; } if (type.IsValueType) { var layoutMetadata = type.GetClassLayout(); cumulativeInstanceFieldPos = Math.Max(cumulativeInstanceFieldPos, layoutMetadata.Size); } SizeAndAlignment instanceByteSizeAndAlignment; var instanceSizeAndAlignment = ComputeInstanceSize(type, cumulativeInstanceFieldPos, largestAlignmentRequirement, out instanceByteSizeAndAlignment); ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout(); computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; computedLayout.FieldSize = instanceSizeAndAlignment.Size; computedLayout.ByteCountUnaligned = instanceByteSizeAndAlignment.Size; computedLayout.ByteCountAlignment = instanceByteSizeAndAlignment.Alignment; computedLayout.Offsets = offsets; return computedLayout; }
private void InitializeTypeDef(Cts.MetadataType entity, TypeDefinition record) { if (entity.ContainingType != null) { var enclosingType = (TypeDefinition)HandleType(entity.ContainingType); record.EnclosingType = enclosingType; enclosingType.NestedTypes.Add(record); var namespaceDefinition = HandleNamespaceDefinition(entity.ContainingType.Module, entity.ContainingType.Namespace); record.NamespaceDefinition = namespaceDefinition; } else { var namespaceDefinition = HandleNamespaceDefinition(entity.Module, entity.Namespace); record.NamespaceDefinition = namespaceDefinition; namespaceDefinition.TypeDefinitions.Add(record); } record.Name = HandleString(entity.Name); Cts.ClassLayoutMetadata layoutMetadata = entity.GetClassLayout(); record.Size = checked ((uint)layoutMetadata.Size); record.PackingSize = checked ((uint)layoutMetadata.PackingSize); record.Flags = GetTypeAttributes(entity); if (entity.HasBaseType) { record.BaseType = HandleType(entity.BaseType); } if (entity.ExplicitlyImplementedInterfaces.Length > 0) { record.Interfaces = entity.ExplicitlyImplementedInterfaces .Where(i => !IsBlocked(i)) .Select(i => HandleType(i)).ToList(); } if (entity.HasInstantiation) { var genericParams = new List <GenericParameter>(entity.Instantiation.Length); foreach (var p in entity.Instantiation) { genericParams.Add(HandleGenericParameter((Cts.GenericParameterDesc)p)); } record.GenericParameters = genericParams; } var fields = new List <Field>(); foreach (var field in entity.GetFields()) { if (_policy.GeneratesMetadata(field)) { fields.Add(HandleFieldDefinition(field)); } } record.Fields = fields; var methods = new List <Method>(); foreach (var method in entity.GetMethods()) { if (_policy.GeneratesMetadata(method)) { methods.Add(HandleMethodDefinition(method)); } } record.Methods = methods; var ecmaEntity = entity as Cts.Ecma.EcmaType; if (ecmaEntity != null) { Ecma.TypeDefinition ecmaRecord = ecmaEntity.MetadataReader.GetTypeDefinition(ecmaEntity.Handle); foreach (var property in ecmaRecord.GetProperties()) { Property prop = HandleProperty(ecmaEntity.EcmaModule, property); if (prop != null) { record.Properties.Add(prop); } } // TODO: Events // TODO: CustomAttributes } }
public unsafe override ComputedStaticFieldLayout ComputeStaticFieldLayout(DefType defType) { MetadataType type = (MetadataType)defType; int numStaticFields = 0; foreach (var field in type.GetFields()) { if (!field.IsStatic || field.HasRva || field.IsLiteral) { continue; } numStaticFields++; } ComputedStaticFieldLayout result; result.GcStatics = new StaticsBlock(); result.NonGcStatics = new StaticsBlock(); result.ThreadStatics = new StaticsBlock(); if (numStaticFields == 0) { result.Offsets = null; return(result); } result.Offsets = new FieldAndOffset[numStaticFields]; PrepareRuntimeSpecificStaticFieldLayout(type.Context, ref result); int index = 0; foreach (var field in type.GetFields()) { // Nonstatic fields, literal fields, and RVA mapped fields don't participate in layout if (!field.IsStatic || field.HasRva || field.IsLiteral) { continue; } StaticsBlock *block = field.IsThreadStatic ? &result.ThreadStatics : field.HasGCStaticBase ? &result.GcStatics : &result.NonGcStatics; SizeAndAlignment sizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType, type.Context.Target.DefaultPackingSize); block->Size = AlignmentHelper.AlignUp(block->Size, sizeAndAlignment.Alignment); result.Offsets[index] = new FieldAndOffset(field, block->Size); block->Size = checked (block->Size + sizeAndAlignment.Size); block->LargestAlignment = Math.Max(block->LargestAlignment, sizeAndAlignment.Alignment); index++; } FinalizeRuntimeSpecificStaticFieldLayout(type.Context, ref result); return(result); }
private void InitializeTypeDef(Cts.MetadataType entity, TypeDefinition record) { Debug.Assert(entity.IsTypeDefinition); Cts.MetadataType containingType = (Cts.MetadataType)entity.ContainingType; if (containingType != null) { var enclosingType = (TypeDefinition)HandleType(containingType); record.EnclosingType = enclosingType; enclosingType.NestedTypes.Add(record); var namespaceDefinition = HandleNamespaceDefinition(containingType.Module, entity.ContainingType.Namespace); record.NamespaceDefinition = namespaceDefinition; } else { var namespaceDefinition = HandleNamespaceDefinition(entity.Module, entity.Namespace); record.NamespaceDefinition = namespaceDefinition; if (entity.IsModuleType) { // These don't get added to the global namespace. // Instead, they have a dedicated field on the scope record. } else { namespaceDefinition.TypeDefinitions.Add(record); } } record.Name = HandleString(entity.Name); Cts.ClassLayoutMetadata layoutMetadata = entity.GetClassLayout(); record.Size = checked ((uint)layoutMetadata.Size); record.PackingSize = checked ((ushort)layoutMetadata.PackingSize); record.Flags = GetTypeAttributes(entity); try { if (entity.HasBaseType) { record.BaseType = HandleType(entity.BaseType); } } catch (Cts.TypeSystemException) when(HasNestedTypes(entity)) { // We might have been forced to generate metadata for a type // that wasn't looked at during code generation because it's an owning // type of a type we did look at. Allow those to generate incomplete // metadata. The ultimate fix is to rewrite metadata generation to be // System.Reflection.Metadata-based as opposed to type system based. // If there's no nested types, this is a bug and should tear down // the compiler at this point. } try { record.Interfaces.Capacity = entity.ExplicitlyImplementedInterfaces.Length; foreach (var interfaceType in entity.ExplicitlyImplementedInterfaces) { if (IsBlocked(interfaceType)) { continue; } record.Interfaces.Add(HandleType(interfaceType)); } } catch (Cts.TypeSystemException) when(HasNestedTypes(entity)) { // We might have been forced to generate metadata for a type // that wasn't looked at during code generation because it's an owning // type of a type we did look at. Allow those to generate incomplete // metadata. The ultimate fix is to rewrite metadata generation to be // System.Reflection.Metadata-based as opposed to type system based. // If there's no nested types, this is a bug and should tear down // the compiler at this point. } if (entity.HasInstantiation) { record.GenericParameters.Capacity = entity.Instantiation.Length; foreach (var p in entity.Instantiation) { record.GenericParameters.Add(HandleGenericParameter((Cts.GenericParameterDesc)p)); } } foreach (var field in entity.GetFields()) { if (_policy.GeneratesMetadata(field)) { record.Fields.Add(HandleFieldDefinition(field)); } } foreach (var method in entity.GetMethods()) { if (_policy.GeneratesMetadata(method)) { record.Methods.Add(HandleMethodDefinition(method)); } } var ecmaEntity = entity as Cts.Ecma.EcmaType; if (ecmaEntity != null) { Ecma.TypeDefinition ecmaRecord = ecmaEntity.MetadataReader.GetTypeDefinition(ecmaEntity.Handle); foreach (var e in ecmaRecord.GetEvents()) { Event evt = HandleEvent(ecmaEntity.EcmaModule, e); if (evt != null) { record.Events.Add(evt); } } foreach (var property in ecmaRecord.GetProperties()) { Property prop = HandleProperty(ecmaEntity.EcmaModule, property); if (prop != null) { record.Properties.Add(prop); } } Ecma.CustomAttributeHandleCollection customAttributes = ecmaRecord.GetCustomAttributes(); if (customAttributes.Count > 0) { record.CustomAttributes = HandleCustomAttributes(ecmaEntity.EcmaModule, customAttributes); } /* COMPLETENESS * foreach (var miHandle in ecmaRecord.GetMethodImplementations()) * { * Ecma.MetadataReader reader = ecmaEntity.EcmaModule.MetadataReader; * * Ecma.MethodImplementation miDef = reader.GetMethodImplementation(miHandle); * * Cts.MethodDesc methodBody = (Cts.MethodDesc)ecmaEntity.EcmaModule.GetObject(miDef.MethodBody); * if (_policy.IsBlocked(methodBody)) * continue; * * Cts.MethodDesc methodDecl = (Cts.MethodDesc)ecmaEntity.EcmaModule.GetObject(miDef.MethodDeclaration); * if (_policy.IsBlocked(methodDecl.GetTypicalMethodDefinition())) * continue; * * MethodImpl methodImplRecord = new MethodImpl * { * MethodBody = HandleQualifiedMethod(methodBody), * MethodDeclaration = HandleQualifiedMethod(methodDecl) * }; * * record.MethodImpls.Add(methodImplRecord); * }*/ }
private void InitializeTypeDef(Cts.MetadataType entity, TypeDefinition record) { Debug.Assert(entity.IsTypeDefinition); Cts.MetadataType containingType = (Cts.MetadataType)entity.ContainingType; if (containingType != null) { var enclosingType = (TypeDefinition)HandleType(containingType); record.EnclosingType = enclosingType; enclosingType.NestedTypes.Add(record); var namespaceDefinition = HandleNamespaceDefinition(containingType.Module, entity.ContainingType.Namespace); record.NamespaceDefinition = namespaceDefinition; } else { var namespaceDefinition = HandleNamespaceDefinition(entity.Module, entity.Namespace); record.NamespaceDefinition = namespaceDefinition; namespaceDefinition.TypeDefinitions.Add(record); } record.Name = HandleString(entity.Name); Cts.ClassLayoutMetadata layoutMetadata = entity.GetClassLayout(); record.Size = checked ((uint)layoutMetadata.Size); record.PackingSize = checked ((ushort)layoutMetadata.PackingSize); record.Flags = GetTypeAttributes(entity); if (entity.HasBaseType) { record.BaseType = HandleType(entity.BaseType); } record.Interfaces.Capacity = entity.ExplicitlyImplementedInterfaces.Length; foreach (var interfaceType in entity.ExplicitlyImplementedInterfaces) { if (IsBlocked(interfaceType)) { continue; } record.Interfaces.Add(HandleType(interfaceType)); } if (entity.HasInstantiation) { record.GenericParameters.Capacity = entity.Instantiation.Length; foreach (var p in entity.Instantiation) { record.GenericParameters.Add(HandleGenericParameter((Cts.GenericParameterDesc)p)); } } foreach (var field in entity.GetFields()) { if (_policy.GeneratesMetadata(field)) { record.Fields.Add(HandleFieldDefinition(field)); } } foreach (var method in entity.GetMethods()) { if (_policy.GeneratesMetadata(method)) { record.Methods.Add(HandleMethodDefinition(method)); } } var ecmaEntity = entity as Cts.Ecma.EcmaType; if (ecmaEntity != null) { Ecma.TypeDefinition ecmaRecord = ecmaEntity.MetadataReader.GetTypeDefinition(ecmaEntity.Handle); foreach (var e in ecmaRecord.GetEvents()) { Event evt = HandleEvent(ecmaEntity.EcmaModule, e); if (evt != null) { record.Events.Add(evt); } } foreach (var property in ecmaRecord.GetProperties()) { Property prop = HandleProperty(ecmaEntity.EcmaModule, property); if (prop != null) { record.Properties.Add(prop); } } Ecma.CustomAttributeHandleCollection customAttributes = ecmaRecord.GetCustomAttributes(); if (customAttributes.Count > 0) { record.CustomAttributes = HandleCustomAttributes(ecmaEntity.EcmaModule, customAttributes); } foreach (var miHandle in ecmaRecord.GetMethodImplementations()) { Ecma.MetadataReader reader = ecmaEntity.EcmaModule.MetadataReader; Ecma.MethodImplementation miDef = reader.GetMethodImplementation(miHandle); Cts.MethodDesc methodBody = (Cts.MethodDesc)ecmaEntity.EcmaModule.GetObject(miDef.MethodBody); if (_policy.IsBlocked(methodBody)) { continue; } Cts.MethodDesc methodDecl = (Cts.MethodDesc)ecmaEntity.EcmaModule.GetObject(miDef.MethodDeclaration); if (_policy.IsBlocked(methodDecl.GetTypicalMethodDefinition())) { continue; } MethodImpl methodImplRecord = new MethodImpl { MethodBody = HandleQualifiedMethod(methodBody), MethodDeclaration = HandleQualifiedMethod(methodDecl) }; record.MethodImpls.Add(methodImplRecord); } } }
private bool CanCompareValueTypeBits(MetadataType type) { Debug.Assert(type.IsValueType); if (type.ContainsGCPointers) { return(false); } if (type.IsGenericDefinition) { return(false); } OverlappingFieldTracker overlappingFieldTracker = new OverlappingFieldTracker(type); bool result = true; foreach (var field in type.GetFields()) { if (field.IsStatic) { continue; } if (!overlappingFieldTracker.TrackField(field)) { // This field overlaps with another field - can't compare memory result = false; break; } TypeDesc fieldType = field.FieldType; if (fieldType.IsPrimitive || fieldType.IsEnum || fieldType.IsPointer || fieldType.IsFunctionPointer) { TypeFlags category = fieldType.UnderlyingType.Category; if (category == TypeFlags.Single || category == TypeFlags.Double) { // Double/Single have weird behaviors around negative/positive zero result = false; break; } } else { // Would be a suprise if this wasn't a valuetype. We checked ContainsGCPointers above. Debug.Assert(fieldType.IsValueType); // If the field overrides Equals, we can't use the fast helper because we need to call the method. if (fieldType.FindVirtualFunctionTargetMethodOnObjectType(_objectEqualsMethod).OwningType == type) { result = false; break; } if (!CanCompareValueTypeBits((MetadataType)fieldType)) { result = false; break; } } } // If there are gaps, we can't memcompare if (result && overlappingFieldTracker.HasGaps) { result = false; } return(result); }
private ValueTypeShapeCharacteristics ComputeHomogeneousFloatAggregateCharacteristic(DefType type) { Debug.Assert(type.IsValueType); MetadataType metadataType = (MetadataType)type; // No HFAs with explicit layout. There may be cases where explicit layout may be still // eligible for HFA, but it is hard to tell the real intent. Make it simple and just // unconditionally disable HFAs for explicit layout. if (metadataType.IsExplicitLayout) { return(ValueTypeShapeCharacteristics.None); } switch (metadataType.Category) { case TypeFlags.Single: case TypeFlags.Double: // These are the primitive types that constitute a HFA type. return(ValueTypeShapeCharacteristics.HomogenousFloatAggregate); case TypeFlags.ValueType: DefType expectedElementType = null; foreach (FieldDesc field in metadataType.GetFields()) { if (field.IsStatic) { continue; } // If a field isn't a DefType, then this type cannot be an HFA type // If a field isn't a HFA type, then this type cannot be an HFA type DefType fieldType = field.FieldType as DefType; if (fieldType == null || !fieldType.IsHfa) { return(ValueTypeShapeCharacteristics.None); } if (expectedElementType == null) { // If we hadn't yet figured out what form of HFA this type might be, we've // now found one case. expectedElementType = fieldType.HfaElementType; Debug.Assert(expectedElementType != null); } else if (expectedElementType != fieldType.HfaElementType) { // If we had already determined the possible HFA type of the current type, but // the field we've encountered is not of that type, then the current type cannot // be an HFA type. return(ValueTypeShapeCharacteristics.None); } } // No fields means this is not HFA. if (expectedElementType == null) { return(ValueTypeShapeCharacteristics.None); } // Types which are indeterminate in field size are not considered to be HFA if (expectedElementType.InstanceFieldSize.IsIndeterminate) { return(ValueTypeShapeCharacteristics.None); } // Types which are indeterminate in field size are not considered to be HFA if (type.InstanceFieldSize.IsIndeterminate) { return(ValueTypeShapeCharacteristics.None); } // Note that we check the total size, but do not perform any checks on number of fields: // - Type of fields can be HFA valuetype itself // - Managed C++ HFA valuetypes have just one <alignment member> of type float to signal that // the valuetype is HFA and explicitly specified size int maxSize = expectedElementType.InstanceFieldSize.AsInt * expectedElementType.Context.Target.MaximumHfaElementCount; if (type.InstanceFieldSize.AsInt > maxSize) { return(ValueTypeShapeCharacteristics.None); } // All the tests passed. This is an HFA type. return(ValueTypeShapeCharacteristics.HomogenousFloatAggregate); } return(ValueTypeShapeCharacteristics.None); }