Example #1
0
        public static void WriteParameterReference(ITextOutput writer, MetadataReader metadata, MethodDefinitionHandle handle, int sequence)
        {
            var methodDefinition = metadata.GetMethodDefinition(handle);
            var signature        = methodDefinition.DecodeSignature(new FullTypeNameSignatureDecoder(metadata), default);
            var parameters       = methodDefinition.GetParameters().Select(p => metadata.GetParameter(p)).ToArray();
            var signatureHeader  = signature.Header;
            int index            = sequence;

            if (signatureHeader.IsInstance && signature.ParameterTypes.Length == parameters.Length)
            {
                index--;
            }
            if (index < 0 || index >= parameters.Length)
            {
                writer.WriteLocalReference(sequence.ToString(), "param_" + index);
            }
            else
            {
                var param = parameters[index];
                if (param.Name.IsNil)
                {
                    writer.WriteLocalReference(sequence.ToString(), "param_" + index);
                }
                else
                {
                    writer.WriteLocalReference(Escape(metadata.GetString(param.Name)), "param_" + index);
                }
            }
        }
        // Inserts dependencies to make the following corner case work (we need MethodTable for `MyStruct[]`):
        //
        // struct MyStruct
        // {
        //     public static int Count(params MyStruct[] myStructs)
        //     {
        //         return myStructs.Length;
        //     }
        //
        //     public static void Main()
        //     {
        //         typeof(MyStruct).InvokeMember(nameof(Count), BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static, null, null, new object[] { default(MyStruct) });
        //     }
        // }
        public static void GetDependenciesFromParamsArray(ref DependencyList dependencies, NodeFactory factory, MethodDesc method)
        {
            MethodSignature sig = method.Signature;

            if (sig.Length < 1 || !sig[sig.Length - 1].IsArray)
            {
                return;
            }

            if (method.GetTypicalMethodDefinition() is not EcmaMethod ecmaMethod)
            {
                return;
            }

            MetadataReader   reader    = ecmaMethod.MetadataReader;
            MethodDefinition methodDef = reader.GetMethodDefinition(ecmaMethod.Handle);

            foreach (ParameterHandle paramHandle in methodDef.GetParameters())
            {
                Parameter param = reader.GetParameter(paramHandle);
                if (param.SequenceNumber == sig.Length /* SequenceNumber is 1-based */)
                {
                    if (!reader.GetCustomAttributeHandle(param.GetCustomAttributes(), "System", "ParamArrayAttribute").IsNil)
                    {
                        dependencies ??= new DependencyList();
                        dependencies.Add(
                            factory.ConstructedTypeSymbol(sig[sig.Length - 1].NormalizeInstantiation()),
                            "Reflection invoke");
                    }

                    break;
                }
            }
        }
Example #3
0
        public override ParameterMetadata[] GetParameterMetadata()
        {
            MetadataReader metadataReader = MetadataReader;

            // Spot check the enums match
            Debug.Assert((int)ParameterAttributes.In == (int)ParameterMetadataAttributes.In);
            Debug.Assert((int)ParameterAttributes.Out == (int)ParameterMetadataAttributes.Out);
            Debug.Assert((int)ParameterAttributes.Optional == (int)ParameterMetadataAttributes.Optional);
            Debug.Assert((int)ParameterAttributes.HasDefault == (int)ParameterMetadataAttributes.HasDefault);
            Debug.Assert((int)ParameterAttributes.HasFieldMarshal == (int)ParameterMetadataAttributes.HasFieldMarshal);

            ParameterHandleCollection parameterHandles = metadataReader.GetMethodDefinition(_handle).GetParameters();

            ParameterMetadata[] parameterMetadataArray = new ParameterMetadata[parameterHandles.Count];
            int index = 0;

            foreach (ParameterHandle parameterHandle in parameterHandles)
            {
                Parameter           parameter           = metadataReader.GetParameter(parameterHandle);
                MarshalAsDescriptor marshalAsDescriptor = GetMarshalAsDescriptor(parameter);
                ParameterMetadata   data = new ParameterMetadata(parameter.SequenceNumber, (ParameterMetadataAttributes)parameter.Attributes, marshalAsDescriptor);
                parameterMetadataArray[index++] = data;
            }
            return(parameterMetadataArray);
        }
Example #4
0
        private void WriteResolvedToken(MethodDefinitionHandle methodHandle, bool isReference)
        {
            var method = metadataReader.GetMethodDefinition(methodHandle);

            // type name
            var containingTypeHandle = method.GetDeclaringType();
            var fullName             = GetFullTypeName(metadataReader, containingTypeHandle);

            if (fullName != null)
            {
                writer.WriteAttributeString(isReference ? "declaringType" :  "containingType", fullName);
            }

            // method name
            writer.WriteAttributeString(isReference ? "methodName" : "name", metadataReader.GetString(method.Name));

            // parameters:
            var parameterNames = (from paramHandle in method.GetParameters()
                                  let parameter = metadataReader.GetParameter(paramHandle)
                                                  where parameter.SequenceNumber > 0 // exclude return parameter
                                                  select parameter.Name.IsNil ? "?" : metadataReader.GetString(parameter.Name)).ToArray();

            if (parameterNames.Length > 0)
            {
                writer.WriteAttributeString("parameterNames", string.Join(", ", parameterNames));
            }
        }
        GetParameters(MetadataReader reader, TypeReferenceTypeProvider typeProvider, GenericContext genericContext, MethodSignature <MetadataTypeReference> signature, ParameterHandleCollection handles)
        {
            var parameters            = new IMetadataParameter[handles.Count];
            var returnValueAttributes = (IReadOnlyList <IMetadataAttribute>)null;

            var maxSequenceNumber = 0;

            foreach (var handle in handles)
            {
                var parameter = reader.GetParameter(handle);
                if (parameter.SequenceNumber == 0)
                {
                    returnValueAttributes = GetAttributes(reader, typeProvider, parameter.GetCustomAttributes(), genericContext);
                    continue;
                }
                if (maxSequenceNumber < parameter.SequenceNumber)
                {
                    maxSequenceNumber = parameter.SequenceNumber;
                }
                var parameterIndex = parameter.SequenceNumber - 1;
                parameters[parameterIndex] = new ReaderParameter(reader, typeProvider, parameter, genericContext, signature.ParameterTypes[parameterIndex]);
            }

            if (maxSequenceNumber == parameters.Length)
            {
                return(parameters, Array.Empty <IMetadataAttribute>());
            }

            // Account for skipping the return parameter
            var correctedLength = new IMetadataParameter[maxSequenceNumber];

            Array.Copy(parameters, correctedLength, correctedLength.Length);
            return(correctedLength, returnValueAttributes);
        }
Example #6
0
        public Variable[] GetParameters()
        {
            if (_cachedParameters != null)
            {
                return(_cachedParameters);
            }

            List <Variable>           variables  = new List <Variable>();
            ImmutableArray <IrisType> paramTypes = _signature.ParameterTypes;
            MetadataReader            mdReader   = Module.Reader;

            foreach (ParameterHandle handle in _methodDef.GetParameters())
            {
                Parameter param = mdReader.GetParameter(handle);
                string    name  = mdReader.GetString(param.Name);
                // A Sequence value of 0 refers to the owner method’s return type; its parameters are then numbered from 1 onwards
                if (param.SequenceNumber == 0)
                {
                    continue;
                }
                variables.Add(new Variable(paramTypes[param.SequenceNumber - 1], name));
            }

            _cachedParameters = variables.ToArray();
            return(_cachedParameters);
        }
        private Mapping <ConstantHandle> MapConstantImpl(ConstantHandle handle)
        {
            Constant         constant = _sourceMetadata.GetConstant(handle);
            Mapping <Handle> parent   = MapHandle(constant.Parent);

            if (parent.Target.IsNil)
            {
                return(new Mapping <ConstantHandle>());
            }

            ConstantHandle targetHandle;

            switch (parent.Target.Kind)
            {
            case HandleKind.Parameter:
                Parameter targetParameter = _targetMetadata.GetParameter((ParameterHandle)parent.Target);
                targetHandle = targetParameter.GetDefaultValue();
                break;

            case HandleKind.FieldDefinition:
                FieldDefinition targetFieldDefinition = _targetMetadata.GetFieldDefinition((FieldDefinitionHandle)parent.Target);
                targetHandle = targetFieldDefinition.GetDefaultValue();
                break;

            case HandleKind.PropertyDefinition:
                PropertyDefinition targetPropertyDefinition = _targetMetadata.GetPropertyDefinition((PropertyDefinitionHandle)parent.Target);
                targetHandle = targetPropertyDefinition.GetDefaultValue();
                break;

            default:
                throw new InvalidOperationException();
            }

            if (targetHandle.IsNil)
            {
                return(new Mapping <ConstantHandle>());
            }

            Constant targetConstant = _targetMetadata.GetConstant(targetHandle);

            if (constant.TypeCode != targetConstant.TypeCode)
            {
                var candidateTargets = ImmutableArray.Create(targetHandle);
                var candidateReasons = ImmutableArray.Create("Mapped constant has a different type.");
                return(new Mapping <ConstantHandle>(candidateTargets, candidateReasons));
            }

            ImmutableArray <byte> sourceContent = _sourceMetadata.GetBlobContent(constant.Value);
            ImmutableArray <byte> targetContent = _targetMetadata.GetBlobContent(targetConstant.Value);

            if (!sourceContent.SequenceEqual(targetContent))
            {
                var candidateTargets = ImmutableArray.Create(targetHandle);
                var candidateReasons = ImmutableArray.Create("Mapped constant has a different value.");
                return(new Mapping <ConstantHandle>(candidateTargets, candidateReasons));
            }

            return(new Mapping <ConstantHandle>(targetHandle));
        }
Example #8
0
 public ParamEntry(PEFile module, ParameterHandle handle)
 {
     this.metadataOffset = module.Reader.PEHeaders.MetadataStartOffset;
     this.module         = module;
     this.metadata       = module.Metadata;
     this.handle         = handle;
     this.param          = metadata.GetParameter(handle);
 }
        public static void AddDependenciesDueToCustomAttributes(ref DependencyList dependencies, NodeFactory factory, EcmaMethod method)
        {
            MetadataReader         reader       = method.MetadataReader;
            MethodDefinitionHandle methodHandle = method.Handle;
            MethodDefinition       methodDef    = reader.GetMethodDefinition(methodHandle);

            // Handle custom attributes on the method
            AddDependenciesDueToCustomAttributes(ref dependencies, factory, method.Module, methodDef.GetCustomAttributes());

            // Handle custom attributes on method parameters
            foreach (ParameterHandle parameterHandle in methodDef.GetParameters())
            {
                Parameter parameter = reader.GetParameter(parameterHandle);
                AddDependenciesDueToCustomAttributes(ref dependencies, factory, method.Module, parameter.GetCustomAttributes());
            }

            // Handle custom attributes on generic method parameters
            foreach (GenericParameterHandle genericParameterHandle in methodDef.GetGenericParameters())
            {
                GenericParameter parameter = reader.GetGenericParameter(genericParameterHandle);
                AddDependenciesDueToCustomAttributes(ref dependencies, factory, method.Module, parameter.GetCustomAttributes());
            }

            // We don't model properties and events as separate entities within the compiler, so ensuring
            // we can generate custom attributes for the associated events and properties from here
            // is as good as any other place.
            //
            // As a performance optimization, we look for associated events and properties only
            // if the method is SpecialName. This is required for CLS compliance and compilers we
            // care about emit accessors like this.
            if ((methodDef.Attributes & MethodAttributes.SpecialName) != 0)
            {
                TypeDefinition declaringType = reader.GetTypeDefinition(methodDef.GetDeclaringType());

                foreach (PropertyDefinitionHandle propertyHandle in declaringType.GetProperties())
                {
                    PropertyDefinition property  = reader.GetPropertyDefinition(propertyHandle);
                    PropertyAccessors  accessors = property.GetAccessors();

                    if (accessors.Getter == methodHandle || accessors.Setter == methodHandle)
                    {
                        AddDependenciesDueToCustomAttributes(ref dependencies, factory, method.Module, property.GetCustomAttributes());
                    }
                }

                foreach (EventDefinitionHandle eventHandle in declaringType.GetEvents())
                {
                    EventDefinition @event    = reader.GetEventDefinition(eventHandle);
                    EventAccessors  accessors = @event.GetAccessors();

                    if (accessors.Adder == methodHandle || accessors.Remover == methodHandle || accessors.Raiser == methodHandle)
                    {
                        AddDependenciesDueToCustomAttributes(ref dependencies, factory, method.Module, @event.GetCustomAttributes());
                    }
                }
            }
        }
Example #10
0
        public static StringHandle[] GetParameterDefNames(this MetadataReader reader)
        {
            var builder = ArrayBuilder <StringHandle> .GetInstance();

            for (int i = 1; i <= reader.GetTableRowCount(TableIndex.Param); i++)
            {
                var handle = MetadataTokens.ParameterHandle(i);
                builder.Add(reader.GetParameter(handle).Name);
            }
            return(builder.ToArrayAndFree());
        }
        public static void AddDependenciesDueToCustomAttributes(ref DependencyList dependencies, NodeFactory factory, EcmaMethod method)
        {
            MetadataReader   reader    = method.MetadataReader;
            MethodDefinition methodDef = reader.GetMethodDefinition(method.Handle);

            // Handle custom attributes on the method
            AddDependenciesDueToCustomAttributes(ref dependencies, factory, method.Module, methodDef.GetCustomAttributes());

            // Handle custom attributes on method parameters
            foreach (ParameterHandle parameterHandle in methodDef.GetParameters())
            {
                Parameter parameter = reader.GetParameter(parameterHandle);
                AddDependenciesDueToCustomAttributes(ref dependencies, factory, method.Module, parameter.GetCustomAttributes());
            }
        }
        /// <summary>
        /// Gets the optional <see cref="ImportAttribute.ServiceId"/> from the <paramref name="ctor"/>
        /// parameter with the given <paramref name="sequenceNumber"/>.
        /// </summary>
        /// <param name="reader"> The extended <see cref="MetadataReader"/>. </param>
        /// <param name="ctor"> The constructor's <see cref="MethodDefinition"/>. </param>
        /// <param name="sequenceNumber"> The sequence number of the parameter whose ServiceId should be retrieved. </param>
        /// <returns> The parameter's optional ServiceId. </returns>
        private static string?GetServiceId(this MetadataReader reader, MethodDefinition ctor, int sequenceNumber)
        {
            foreach (var parameterHandle in ctor.GetParameters())
            {
                var parameter = reader.GetParameter(parameterHandle);
                if (parameter.SequenceNumber != sequenceNumber)
                {
                    continue;
                }

                foreach (var attributeHandle in parameter.GetCustomAttributes())
                {
                    var customAttribute = reader.GetCustomAttribute(attributeHandle);
                    if (customAttribute.Constructor.Kind != HandleKind.MemberReference)
                    {
                        return(null);
                    }

                    var attributeCtor = reader.GetMemberReference((MemberReferenceHandle)customAttribute.Constructor);
                    if (attributeCtor.Parent.Kind != HandleKind.TypeReference)
                    {
                        return(null);
                    }

                    var attributeType = reader.GetTypeReference((TypeReferenceHandle)attributeCtor.Parent);
                    var name          = reader.GetString(attributeType.Name);
                    var @namespace    = reader.GetString(attributeType.Namespace);
                    if (typeof(ImportAttribute).Name.Equals(name, StringComparison.Ordinal) &&
                        typeof(ImportAttribute).Namespace.Equals(@namespace, StringComparison.Ordinal))
                    {
                        var attribute = customAttribute.DecodeValue(new TypeDescriptorAttributeProvider());
                        foreach (var argument in attribute.FixedArguments)
                        {
                            if (argument.Value is string serviceId)
                            {
                                return(serviceId);
                            }
                        }
                    }
                }
            }

            return(null);
        }
        public Variable[] GetParameters()
        {
            if (_cachedParameters != null)
            {
                return(_cachedParameters);
            }

            List <Variable>           variables  = new List <Variable>();
            ImmutableArray <IrisType> paramTypes = _signature.ParameterTypes;
            MetadataReader            mdReader   = Module.Reader;

            foreach (ParameterHandle handle in _methodDef.GetParameters())
            {
                Parameter param = mdReader.GetParameter(handle);
                string    name  = mdReader.GetString(param.Name);
                variables.Add(new Variable(paramTypes[param.SequenceNumber - 1], name));
            }

            _cachedParameters = variables.ToArray();
            return(_cachedParameters);
        }
 private static void Main(string[] args)
 {
     foreach (string fileName in new string[] { @"C:\git\corert\bin\Windows_NT.x64.Debug\ILVerification.Tests\Tests\InterfaceImplementation.dll" })
     {
         Console.WriteLine("Lib: " + fileName);
         PEReader       peReader       = new PEReader(File.OpenRead(fileName));
         MetadataReader metadataReader = peReader.GetMetadataReader(MetadataReaderOptions.None);
         Console.WriteLine("IsAssembly " + metadataReader.IsAssembly);
         foreach (TypeDefinitionHandle td in metadataReader.TypeDefinitions)
         {
             TypeDefinition typeDefinition = metadataReader.GetTypeDefinition(td);
             if (metadataReader.GetString(typeDefinition.Name) != "InvalidReturnTypeM1_InvalidType_InterfaceMethodNotImplemented")
             {
                 continue;
             }
             Console.WriteLine("TypeDefHandle token:" + metadataReader.GetToken(td).ToString("X8"));
             Console.WriteLine("TypeDefinition name: " + metadataReader.GetString(typeDefinition.Name) + ((((int)typeDefinition.Attributes & 0x00000020) == 0x00000020) ? " [IsInterface]" : ""));
             Console.WriteLine("Attributes name: " + typeDefinition.Attributes);
             foreach (InterfaceImplementationHandle interfaceImplementation in typeDefinition.GetInterfaceImplementations())
             {
                 InterfaceImplementation im = metadataReader.GetInterfaceImplementation(interfaceImplementation);
                 Console.WriteLine("InterfaceImplementationHandle:" + metadataReader.GetToken(im.Interface).ToString("X8"));
             }
             foreach (MethodDefinitionHandle mdh in typeDefinition.GetMethods())
             {
                 MethodDefinition md = metadataReader.GetMethodDefinition(mdh);
                 Console.WriteLine(" Method name: " + metadataReader.GetString(md.Name));
                 foreach (ParameterHandle ph in md.GetParameters())
                 {
                     Parameter parameterDef = metadataReader.GetParameter(ph);
                     Console.WriteLine("     Param name: " + metadataReader.GetString(parameterDef.Name) + (parameterDef.SequenceNumber == 0 ? "- return value" : ""));
                 }
                 Console.WriteLine("MethodDefinitionHandle:" + metadataReader.GetToken(mdh).ToString("X8"));
             }
             Console.WriteLine("----");
         }
     }
 }
        private void WriteParam()
        {
            AddHeader(
                "Name",
                "Seq#",
                "Attributes",
                "Marshalling"
                );

            for (int i = 1, count = reader.GetTableRowCount(TableIndex.Param); i <= count; i++)
            {
                var entry = reader.GetParameter(MetadataTokens.ParameterHandle(i));

                AddRow(
                    Literal(entry.Name),
                    entry.SequenceNumber.ToString(),
                    EnumValue <int>(entry.Attributes),
                    Literal(entry.GetMarshallingDescriptor())
                    );
            }

            WriteRows("Param (0x08):");
        }
Example #16
0
 public static Parameter GetParameter(MetadataReader reader, ParameterHandle handle)
 {
     return(reader.GetParameter(handle));
 }
Example #17
0
        /// <summary>
        /// Param Table Columns:
        ///     Name (offset to #String)
        ///     Flags, Sequence (2 byte unsigned)
        /// </summary>
        private void ValidateParam(MetadataReader reader, uint startIndex, uint count, bool isMod = false)
        {
            if (count == 0)
            {
                return;
            }

            // AppCS - 7
            var expNames = new string[] { "p", "t", "p", "value", "t", "value", "t" };

            // =================
            // ModuleVB01 - 20
            var modNames = new string[]
            {
                "index", "index", "value", "em", "cls",    "del", "obj", "obj", "o", "e",
                "p", "TargetObject", "TargetMethod", "o", "e",
                "DelegateCallback", "DelegateAsyncState", "DelegateAsyncResult", "o", "e",
            };
            var modFlags = new ushort[] { 0, 0, 0, 0, 0x1010, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };
            var modSeqs = new ushort[] { 1, 1, 2, 1, 2, 1, 1, 1, 1, 2, 1, 1, 2, 1, 2, 3, 4, 1, 1, 2, };

            if (startIndex > reader.ParamTable.NumberOfRows)
            {
                return;
            }

            uint zeroBased = startIndex - 1;
            uint delta = count;

            // Last one
            if (0xF0000000 == count)
            {
                delta = (uint)reader.ParamTable.NumberOfRows - zeroBased;
                if (0 == delta)
                {
                    return;
                }
            }

            Assert.InRange((uint)reader.ParamTable.NumberOfRows, zeroBased + delta, uint.MaxValue); // 1 based
            for (uint i = zeroBased; i < zeroBased + delta; i++)
            {
                var handle = ParameterHandle.FromRowId((int)i + 1);
                var row = reader.GetParameter(handle);

                // Console.WriteLine("P: {0}", GetStringData(row.Name));
                if (isMod)
                {
                    Assert.Equal(modNames[i], reader.GetString(row.Name));
                    Assert.Equal(modFlags[i], (ushort)row.Attributes);
                    Assert.Equal(modSeqs[i], row.SequenceNumber);
                }
                else
                {
                    Assert.Equal(expNames[i], reader.GetString(row.Name));
                    Assert.Equal((ushort)0, (ushort)row.Attributes);
                    Assert.Equal((ushort)1, row.SequenceNumber);
                }
            } // for
        }
Example #18
0
 public static StringHandle[] GetParameterDefNames(this MetadataReader reader)
 {
     return(reader.GetParameters().Select(handle => reader.GetParameter(handle).Name).ToArray());
 }
Example #19
0
 public static Parameter GetParameter(this ParameterHandle handle, MetadataReader reader) => reader.GetParameter(handle);
Example #20
0
 public static string ToString(this MetadataReader reader, ParameterHandle x) => reader.ToString(reader.GetParameter(x));
Example #21
0
            protected override TypeAnnotations CreateValueFromKey(TypeDesc key)
            {
                // We scan the entire type at this point; the reason for doing that is properties.
                //
                // We allow annotating properties, but those annotations need to flow onto individual get/set methods
                // and backing fields. Without scanning all properties, we can't answer questions about fields/methods.
                // And if we're going over all properties, we might as well go over everything else to keep things simple.

                Debug.Assert(key.IsTypeDefinition);
                if (key is not EcmaType ecmaType)
                {
                    return(new TypeAnnotations(key, DynamicallyAccessedMemberTypes.None, null, null, null));
                }

                MetadataReader reader = ecmaType.MetadataReader;

                // class, interface, struct can have annotations
                TypeDefinition typeDef = reader.GetTypeDefinition(ecmaType.Handle);
                DynamicallyAccessedMemberTypes typeAnnotation = GetMemberTypesForDynamicallyAccessedMembersAttribute(reader, typeDef.GetCustomAttributes());

                try
                {
                    // Also inherit annotation from bases
                    TypeDesc baseType = key.BaseType;
                    while (baseType != null)
                    {
                        TypeDefinition baseTypeDef = reader.GetTypeDefinition(((EcmaType)baseType.GetTypeDefinition()).Handle);
                        typeAnnotation |= GetMemberTypesForDynamicallyAccessedMembersAttribute(reader, baseTypeDef.GetCustomAttributes());
                        baseType        = baseType.BaseType;
                    }

                    // And inherit them from interfaces
                    foreach (DefType runtimeInterface in key.RuntimeInterfaces)
                    {
                        TypeDefinition interfaceTypeDef = reader.GetTypeDefinition(((EcmaType)runtimeInterface.GetTypeDefinition()).Handle);
                        typeAnnotation |= GetMemberTypesForDynamicallyAccessedMembersAttribute(reader, interfaceTypeDef.GetCustomAttributes());
                    }
                }
                catch (TypeSystemException)
                {
                    // If the class hierarchy is not walkable, just stop collecting the annotations.
                }

                var annotatedFields = new ArrayBuilder <FieldAnnotation>();

                // First go over all fields with an explicit annotation
                foreach (EcmaField field in ecmaType.GetFields())
                {
                    FieldDefinition fieldDef = reader.GetFieldDefinition(field.Handle);
                    DynamicallyAccessedMemberTypes annotation =
                        GetMemberTypesForDynamicallyAccessedMembersAttribute(reader, fieldDef.GetCustomAttributes());
                    if (annotation == DynamicallyAccessedMemberTypes.None)
                    {
                        continue;
                    }

                    if (!IsTypeInterestingForDataflow(field.FieldType))
                    {
                        // Already know that there's a non-empty annotation on a field which is not System.Type/String and we're about to ignore it
                        _logger.LogWarning(field, DiagnosticId.DynamicallyAccessedMembersOnFieldCanOnlyApplyToTypesOrStrings, field.GetDisplayName());
                        continue;
                    }

                    annotatedFields.Add(new FieldAnnotation(field, annotation));
                }

                var annotatedMethods = new ArrayBuilder <MethodAnnotations>();

                // Next go over all methods with an explicit annotation
                foreach (EcmaMethod method in ecmaType.GetMethods())
                {
                    DynamicallyAccessedMemberTypes[]? paramAnnotations = null;

                    // We convert indices from metadata space to IL space here.
                    // IL space assigns index 0 to the `this` parameter on instance methods.

                    DynamicallyAccessedMemberTypes methodMemberTypes =
                        GetMemberTypesForDynamicallyAccessedMembersAttribute(reader, reader.GetMethodDefinition(method.Handle).GetCustomAttributes());

                    MethodSignature signature;
                    try
                    {
                        signature = method.Signature;
                    }
                    catch (TypeSystemException)
                    {
                        // If we cannot resolve things in the signature, just move along.
                        continue;
                    }

                    int offset;
                    if (!signature.IsStatic)
                    {
                        offset = 1;
                    }
                    else
                    {
                        offset = 0;
                    }

                    // If there's an annotation on the method itself and it's one of the special types (System.Type for example)
                    // treat that annotation as annotating the "this" parameter.
                    if (methodMemberTypes != DynamicallyAccessedMemberTypes.None)
                    {
                        if (IsTypeInterestingForDataflow(method.OwningType) && !signature.IsStatic)
                        {
                            paramAnnotations    = new DynamicallyAccessedMemberTypes[signature.Length + offset];
                            paramAnnotations[0] = methodMemberTypes;
                        }
                        else
                        {
                            _logger.LogWarning(method, DiagnosticId.DynamicallyAccessedMembersIsNotAllowedOnMethods);
                        }
                    }

                    MethodDefinition          methodDef        = reader.GetMethodDefinition(method.Handle);
                    ParameterHandleCollection parameterHandles = methodDef.GetParameters();

                    DynamicallyAccessedMemberTypes returnAnnotation = DynamicallyAccessedMemberTypes.None;

                    foreach (ParameterHandle parameterHandle in parameterHandles)
                    {
                        Parameter parameter = reader.GetParameter(parameterHandle);

                        if (parameter.SequenceNumber == 0)
                        {
                            // this is the return parameter
                            returnAnnotation = GetMemberTypesForDynamicallyAccessedMembersAttribute(reader, parameter.GetCustomAttributes());
                            if (returnAnnotation != DynamicallyAccessedMemberTypes.None && !IsTypeInterestingForDataflow(signature.ReturnType))
                            {
                                _logger.LogWarning(method, DiagnosticId.DynamicallyAccessedMembersOnMethodReturnValueCanOnlyApplyToTypesOrStrings, method.GetDisplayName());
                            }
                        }
                        else
                        {
                            DynamicallyAccessedMemberTypes pa = GetMemberTypesForDynamicallyAccessedMembersAttribute(reader, parameter.GetCustomAttributes());
                            if (pa == DynamicallyAccessedMemberTypes.None)
                            {
                                continue;
                            }

                            if (!IsTypeInterestingForDataflow(signature[parameter.SequenceNumber - 1]))
                            {
                                _logger.LogWarning(method, DiagnosticId.DynamicallyAccessedMembersOnMethodParameterCanOnlyApplyToTypesOrStrings, DiagnosticUtilities.GetParameterNameForErrorMessage(method, parameter.SequenceNumber - 1), method.GetDisplayName());
                                continue;
                            }

                            if (paramAnnotations == null)
                            {
                                paramAnnotations = new DynamicallyAccessedMemberTypes[signature.Length + offset];
                            }
                            paramAnnotations[parameter.SequenceNumber - 1 + offset] = pa;
                        }
                    }

                    DynamicallyAccessedMemberTypes[]? genericParameterAnnotations = null;
                    foreach (EcmaGenericParameter genericParameter in method.Instantiation)
                    {
                        GenericParameter genericParameterDef = reader.GetGenericParameter(genericParameter.Handle);
                        var annotation = GetMemberTypesForDynamicallyAccessedMembersAttribute(reader, genericParameterDef.GetCustomAttributes());
                        if (annotation != DynamicallyAccessedMemberTypes.None)
                        {
                            if (genericParameterAnnotations == null)
                            {
                                genericParameterAnnotations = new DynamicallyAccessedMemberTypes[method.Instantiation.Length];
                            }
                            genericParameterAnnotations[genericParameter.Index] = annotation;
                        }
                    }

                    if (returnAnnotation != DynamicallyAccessedMemberTypes.None || paramAnnotations != null || genericParameterAnnotations != null)
                    {
                        annotatedMethods.Add(new MethodAnnotations(method, paramAnnotations, returnAnnotation, genericParameterAnnotations));
                    }
                }

                // Next up are properties. Annotations on properties are kind of meta because we need to
                // map them to annotations on methods/fields. They're syntactic sugar - what they do is expressible
                // by placing attribute on the accessor/backing field. For complex properties, that's what people
                // will need to do anyway. Like so:
                //
                // [field: Attribute]
                // Type MyProperty
                // {
                //     [return: Attribute]
                //     get;
                //     [value: Attribute]
                //     set;
                //  }

                foreach (PropertyDefinitionHandle propertyHandle in reader.GetTypeDefinition(ecmaType.Handle).GetProperties())
                {
                    DynamicallyAccessedMemberTypes annotation = GetMemberTypesForDynamicallyAccessedMembersAttribute(
                        reader, reader.GetPropertyDefinition(propertyHandle).GetCustomAttributes());
                    if (annotation == DynamicallyAccessedMemberTypes.None)
                    {
                        continue;
                    }

                    PropertyPseudoDesc property = new PropertyPseudoDesc(ecmaType, propertyHandle);

                    if (!IsTypeInterestingForDataflow(property.Signature.ReturnType))
                    {
                        _logger.LogWarning(property, DiagnosticId.DynamicallyAccessedMembersOnPropertyCanOnlyApplyToTypesOrStrings, property.GetDisplayName());
                        continue;
                    }

                    FieldDesc?backingFieldFromSetter = null;

                    // Propagate the annotation to the setter method
                    MethodDesc setMethod = property.SetMethod;
                    if (setMethod != null)
                    {
                        // Abstract property backing field propagation doesn't make sense, and any derived property will be validated
                        // to have the exact same annotations on getter/setter, and thus if it has a detectable backing field that will be validated as well.
                        MethodIL methodBody = _ilProvider.GetMethodIL(setMethod);
                        if (methodBody != null)
                        {
                            // Look for the compiler generated backing field. If it doesn't work out simply move on. In such case we would still
                            // propagate the annotation to the setter/getter and later on when analyzing the setter/getter we will warn
                            // that the field (which ever it is) must be annotated as well.
                            ScanMethodBodyForFieldAccess(methodBody, write: true, out backingFieldFromSetter);
                        }

                        if (annotatedMethods.Any(a => a.Method == setMethod))
                        {
                            _logger.LogWarning(setMethod, DiagnosticId.DynamicallyAccessedMembersConflictsBetweenPropertyAndAccessor, property.GetDisplayName(), setMethod.GetDisplayName());
                        }
                        else
                        {
                            int offset = setMethod.Signature.IsStatic ? 0 : 1;
                            if (setMethod.Signature.Length > 0)
                            {
                                DynamicallyAccessedMemberTypes[] paramAnnotations = new DynamicallyAccessedMemberTypes[setMethod.Signature.Length + offset];
                                paramAnnotations[paramAnnotations.Length - 1] = annotation;
                                annotatedMethods.Add(new MethodAnnotations(setMethod, paramAnnotations, DynamicallyAccessedMemberTypes.None, null));
                            }
                        }
                    }

                    FieldDesc?backingFieldFromGetter = null;

                    // Propagate the annotation to the getter method
                    MethodDesc getMethod = property.GetMethod;
                    if (getMethod != null)
                    {
                        // Abstract property backing field propagation doesn't make sense, and any derived property will be validated
                        // to have the exact same annotations on getter/setter, and thus if it has a detectable backing field that will be validated as well.
                        MethodIL methodBody = _ilProvider.GetMethodIL(getMethod);
                        if (methodBody != null)
                        {
                            // Look for the compiler generated backing field. If it doesn't work out simply move on. In such case we would still
                            // propagate the annotation to the setter/getter and later on when analyzing the setter/getter we will warn
                            // that the field (which ever it is) must be annotated as well.
                            ScanMethodBodyForFieldAccess(methodBody, write: false, out backingFieldFromGetter);
                        }

                        if (annotatedMethods.Any(a => a.Method == getMethod))
                        {
                            _logger.LogWarning(getMethod, DiagnosticId.DynamicallyAccessedMembersConflictsBetweenPropertyAndAccessor, property.GetDisplayName(), getMethod.GetDisplayName());
                        }
                        else
                        {
                            annotatedMethods.Add(new MethodAnnotations(getMethod, null, annotation, null));
                        }
                    }

                    FieldDesc?backingField;
                    if (backingFieldFromGetter != null && backingFieldFromSetter != null &&
                        backingFieldFromGetter != backingFieldFromSetter)
                    {
                        _logger.LogWarning(property, DiagnosticId.DynamicallyAccessedMembersCouldNotFindBackingField, property.GetDisplayName());
                        backingField = null;
                    }
                    else
                    {
                        backingField = backingFieldFromGetter ?? backingFieldFromSetter;
                    }

                    if (backingField != null)
                    {
                        if (annotatedFields.Any(a => a.Field == backingField))
                        {
                            _logger.LogWarning(backingField, DiagnosticId.DynamicallyAccessedMembersOnPropertyConflictsWithBackingField, property.GetDisplayName(), backingField.GetDisplayName());
                        }
                        else
                        {
                            annotatedFields.Add(new FieldAnnotation(backingField, annotation));
                        }
                    }
                }

                DynamicallyAccessedMemberTypes[]? typeGenericParameterAnnotations = null;
                foreach (EcmaGenericParameter genericParameter in ecmaType.Instantiation)
                {
                    GenericParameter genericParameterDef = reader.GetGenericParameter(genericParameter.Handle);

                    var annotation = GetMemberTypesForDynamicallyAccessedMembersAttribute(reader, genericParameterDef.GetCustomAttributes());
                    if (annotation != DynamicallyAccessedMemberTypes.None)
                    {
                        if (typeGenericParameterAnnotations == null)
                        {
                            typeGenericParameterAnnotations = new DynamicallyAccessedMemberTypes[ecmaType.Instantiation.Length];
                        }
                        typeGenericParameterAnnotations[genericParameter.Index] = annotation;
                    }
                }

                return(new TypeAnnotations(ecmaType, typeAnnotation, annotatedMethods.ToArray(), annotatedFields.ToArray(), typeGenericParameterAnnotations));
            }