Пример #1
0
        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++;
            }
Пример #2
0
 public override IEnumerable <FieldDesc> GetFields()
 {
     foreach (var fieldDef in _typeDef.GetFields())
     {
         yield return(_typeDef.Context.GetFieldForInstantiatedType(fieldDef, this));
     }
 }
Пример #3
0
 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);
                 }
             }
         }
     }
 }
Пример #4
0
 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);
                 }
             }
         }
     }
 }
Пример #5
0
        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);
        }
Пример #6
0
        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);
        }
Пример #7
0
        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;
        }
Пример #9
0
        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
            }
        }
Пример #10
0
        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);
        }
Пример #11
0
        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);
                 * }*/
            }
Пример #12
0
        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);
        }
Пример #14
0
        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);
        }