示例#1
0
        public override MethodIL GetMethodIL(MethodDesc method)
        {
            RemoveAction action = GetAction(method);

            switch (action)
            {
            case RemoveAction.Nothing:
                return(_baseILProvider.GetMethodIL(method));

            case RemoveAction.ConvertToStub:
                if (method.Signature.ReturnType.IsVoid)
                {
                    return(new ILStubMethodIL(method, new byte[] { (byte)ILOpcode.ret }, Array.Empty <LocalVariableDefinition>(), null));
                }
                else if (method.Signature.ReturnType.Category == TypeFlags.Boolean)
                {
                    return(new ILStubMethodIL(method, new byte[] { (byte)ILOpcode.ldc_i4_0, (byte)ILOpcode.ret }, Array.Empty <LocalVariableDefinition>(), null));
                }
                else
                {
                    goto default;
                }

            case RemoveAction.ConvertToTrueStub:
                return(new ILStubMethodIL(method, new byte[] { (byte)ILOpcode.ldc_i4_1, (byte)ILOpcode.ret }, Array.Empty <LocalVariableDefinition>(), null));

            case RemoveAction.ConvertToGetResourceStringStub:
                return(new ILStubMethodIL(method, new byte[] {
                    (byte)ILOpcode.ldarg_0,
                    (byte)ILOpcode.ret
                },
                                          Array.Empty <LocalVariableDefinition>(), null));

            case RemoveAction.ConvertToThrow:
                return(new ILStubMethodIL(method, new byte[] { (byte)ILOpcode.ldnull, (byte)ILOpcode.throw_ }, Array.Empty <LocalVariableDefinition>(), null));

            case RemoveAction.ConvertToGetKnownObjectComparer:
            case RemoveAction.ConvertToGetKnownObjectEqualityComparer:
            {
                TypeSystemContext context      = method.Context;
                MetadataType      comparerType =
                    action == RemoveAction.ConvertToGetKnownObjectComparer ?
                    context.SystemModule.GetType("System.Collections.Generic", "ObjectComparer`1") :
                    context.SystemModule.GetType("System.Collections.Generic", "ObjectEqualityComparer`1");

                MethodDesc methodDef = method.GetTypicalMethodDefinition();

                ILEmitter    emitter    = new ILEmitter();
                ILCodeStream codeStream = emitter.NewCodeStream();
                codeStream.Emit(ILOpcode.newobj, emitter.NewToken(comparerType.MakeInstantiatedType(context.GetSignatureVariable(0, method: false)).GetDefaultConstructor()));
                codeStream.Emit(ILOpcode.dup);
                codeStream.Emit(ILOpcode.stsfld, emitter.NewToken(methodDef.OwningType.InstantiateAsOpen().GetField("_default")));
                codeStream.Emit(ILOpcode.ret);
                return(new InstantiatedMethodIL(method, emitter.Link(methodDef)));
            }

            default:
                throw new NotImplementedException();
            }
        }
示例#2
0
        internal MethodIL GetMethodIL(MethodDesc method)
        {
            // Flush the cache when it grows too big
            if (_methodILCache.Count > 1000)
            {
                _methodILCache = new ILProvider(new PInvokeILProvider(new PInvokeILEmitterConfiguration(forceLazyResolution: true), null));
            }

            return(_methodILCache.GetMethodIL(method));
        }
示例#3
0
        public MethodIL GetMethodIL(MethodDesc method)
        {
            // Flush the cache when it grows too big
            if (_methodILCache.Count > 1000)
            {
                _methodILCache = new ILProvider();
            }

            return(_methodILCache.GetMethodIL(method));
        }
示例#4
0
        internal MethodIL GetMethodIL(MethodDesc method)
        {
            // Flush the cache when it grows too big
            if (_methodILCache.Count > 1000)
            {
                _methodILCache = new ILProvider(_pInvokeILProvider);
            }

            return(_methodILCache.GetMethodIL(method));
        }
示例#5
0
            public override MethodIL GetMethodIL(MethodDesc method)
            {
                MethodIL result = _primaryILProvider.GetMethodIL(method);

                if (result == null && method.IsPInvoke)
                {
                    result = _pinvokeProvider.GetMethodIL(method);
                }

                return(result);
            }
示例#6
0
            protected override MethodILData CreateValueFromKey(MethodDesc key)
            {
                MethodIL methodIL = ILProvider.GetMethodIL(key);

                if (methodIL == null &&
                    key.IsPInvoke &&
                    _compilationModuleGroup.GeneratesPInvoke(key))
                {
                    methodIL = PInvokeILEmitter.EmitIL(key);
                }

                return(new MethodILData()
                {
                    Method = key, MethodIL = methodIL
                });
            }
        private Dictionary <MethodDesc, MethodDesc> LoadDynamicInvokeStubs()
        {
            MetadataType typeWithMetadataMappings = (MetadataType)_metadataDescribingModule.GetTypeByCustomAttributeTypeName(MetadataMappingTypeName);
            Dictionary <MethodDesc, MethodDesc> dynamicInvokeMapTable = new Dictionary <MethodDesc, MethodDesc>();
            MethodDesc dynamicInvokeStubDescriptorMethod = typeWithMetadataMappings.GetMethod("DynamicInvokeStubs", null);

            if (dynamicInvokeStubDescriptorMethod == null)
            {
                return(dynamicInvokeMapTable);
            }

            ILProvider     ilProvider = new ILProvider(null);
            ILStreamReader il         = new ILStreamReader(ilProvider.GetMethodIL(dynamicInvokeStubDescriptorMethod));

            // structure is
            // REPEAT N TIMES
            //ldtoken method
            //ldtoken dynamicInvokeStubMethod
            //pop
            //pop
            while (true)
            {
                if (il.TryReadRet()) // ret
                {
                    break;
                }

                MethodDesc method = il.ReadLdtokenAsTypeSystemEntity() as MethodDesc;
                MethodDesc dynamicMethodInvokeStub = il.ReadLdtokenAsTypeSystemEntity() as MethodDesc;
                il.ReadPop();
                il.ReadPop();

                if ((method != null) && (dynamicMethodInvokeStub != null))
                {
                    dynamicInvokeMapTable[method] = dynamicMethodInvokeStub;
                }
                else
                {
                    throw new BadImageFormatException();
                }
            }

            return(dynamicInvokeMapTable);
        }
示例#8
0
        public override MethodIL GetMethodIL(MethodDesc method)
        {
            BodySubstitution substitution = GetSubstitution(method);

            if (substitution != null)
            {
                return(substitution.EmitIL(method));
            }

            // BEGIN TEMPORARY WORKAROUND
            //
            // The following lines should just be:
            // return _nestedILProvider.GetMethodIL(method);
            // But we want to allow this to be used as a general-purpose IL provider.
            //
            // Rewriting all IL has compilation throughput hit we don't want.
            MethodIL result = _nestedILProvider.GetMethodIL(method);

            if (result != null)
            {
                var resultDef = result.GetMethodILDefinition();
                if (resultDef != result)
                {
                    MethodIL newBodyDef = GetMethodILWithInlinedSubstitutions(resultDef);

                    // If we didn't rewrite the body, we can keep the existing result.
                    if (newBodyDef != resultDef)
                    {
                        result = new InstantiatedMethodIL(method, newBodyDef);
                    }
                }
                else
                {
                    result = GetMethodILWithInlinedSubstitutions(result);
                }
            }
            return(result);
            // END TEMPORARY WORKAROUND
        }
示例#9
0
        public override MethodIL GetMethodIL(MethodDesc method)
        {
            switch (GetAction(method))
            {
            case RemoveAction.Nothing:
                return(_baseILProvider.GetMethodIL(method));

            case RemoveAction.ConvertToStub:
                if (method.Signature.ReturnType.IsVoid)
                {
                    return(new ILStubMethodIL(method, new byte[] { (byte)ILOpcode.ret }, Array.Empty <LocalVariableDefinition>(), null));
                }
                else if (method.Signature.ReturnType.Category == TypeFlags.Boolean)
                {
                    return(new ILStubMethodIL(method, new byte[] { (byte)ILOpcode.ldc_i4_0, (byte)ILOpcode.ret }, Array.Empty <LocalVariableDefinition>(), null));
                }
                else
                {
                    goto default;
                }

            case RemoveAction.ConvertToTrueStub:
                return(new ILStubMethodIL(method, new byte[] { (byte)ILOpcode.ldc_i4_1, (byte)ILOpcode.ret }, Array.Empty <LocalVariableDefinition>(), null));

            case RemoveAction.ConvertToGetResourceStringStub:
                return(new ILStubMethodIL(method, new byte[] {
                    (byte)ILOpcode.ldarg_0,
                    (byte)ILOpcode.ret
                },
                                          Array.Empty <LocalVariableDefinition>(), null));

            case RemoveAction.ConvertToThrow:
                return(new ILStubMethodIL(method, new byte[] { (byte)ILOpcode.ldnull, (byte)ILOpcode.throw_ }, Array.Empty <LocalVariableDefinition>(), null));

            default:
                throw new NotImplementedException();
            }
        }
        private MetadataLoadedInfo LoadMetadata()
        {
            HashSet <ModuleDesc> metadataModules          = new HashSet <ModuleDesc>();
            MetadataType         typeWithMetadataMappings = (MetadataType)_metadataDescribingModule.GetTypeByCustomAttributeTypeName(MetadataMappingTypeName);

            MethodDesc fullMetadataMethod = typeWithMetadataMappings.GetMethod("Metadata", null);
            MethodDesc weakMetadataMethod = typeWithMetadataMappings.GetMethod("WeakMetadata", null);

            ILProvider ilProvider = new ILProvider(null);

            MetadataLoadedInfo result = new MetadataLoadedInfo();

            if (fullMetadataMethod != null)
            {
                MethodIL fullMethodIL = ilProvider.GetMethodIL(fullMetadataMethod);
                ReadMetadataMethod(fullMethodIL, ref result.AllTypeMappings, ref result.MethodMappings, ref result.FieldMappings, ref metadataModules);
                foreach (var mapping in result.AllTypeMappings)
                {
                    result.TypesWithStrongMetadataMappings.Add(mapping.Key);
                }
            }

            if (weakMetadataMethod != null)
            {
                MethodIL weakMethodIL = ilProvider.GetMethodIL(weakMetadataMethod);
                Dictionary <MethodDesc, int> weakMethodMappings = new Dictionary <MethodDesc, int>();
                Dictionary <FieldDesc, int>  weakFieldMappings  = new Dictionary <FieldDesc, int>();
                ReadMetadataMethod(weakMethodIL, ref result.AllTypeMappings, ref weakMethodMappings, ref weakFieldMappings, ref metadataModules);
                if ((weakMethodMappings.Count > 0) || (weakFieldMappings.Count > 0))
                {
                    // the format does not permit weak field/method mappings
                    throw new BadImageFormatException();
                }
            }

            result.MetadataModules = ImmutableArray.CreateRange(metadataModules);

            ImmutableArray <ModuleDesc> .Builder externalMetadataModulesBuilder = ImmutableArray.CreateBuilder <ModuleDesc>();
            ImmutableArray <ModuleDesc> .Builder localMetadataModulesBuilder    = ImmutableArray.CreateBuilder <ModuleDesc>();
            foreach (ModuleDesc module in result.MetadataModules)
            {
                if (!_compilationModules.Contains(module))
                {
                    externalMetadataModulesBuilder.Add(module);
                }
                else
                {
                    localMetadataModulesBuilder.Add(module);
                }
            }
            result.ExternalMetadataModules = externalMetadataModulesBuilder.ToImmutable();
            result.LocalMetadataModules    = localMetadataModulesBuilder.ToImmutable();

            // TODO! Replace with something more complete that capture the generic instantiations that the pre-analysis
            // indicates should have been present
            foreach (var pair in result.MethodMappings)
            {
                MethodDesc reflectableMethod = pair.Key;

                if (reflectableMethod.HasInstantiation)
                {
                    continue;
                }

                if (reflectableMethod.OwningType.HasInstantiation)
                {
                    continue;
                }

                MethodDesc typicalDynamicInvokeStub;
                if (!_dynamicInvokeStubs.Value.TryGetValue(reflectableMethod, out typicalDynamicInvokeStub))
                {
                    continue;
                }

                MethodDesc instantiatiatedDynamicInvokeStub = InstantiateDynamicInvokeMethodForMethod(typicalDynamicInvokeStub, reflectableMethod);
                result.DynamicInvokeCompiledMethods.Add(instantiatiatedDynamicInvokeStub.GetCanonMethodTarget(CanonicalFormKind.Specific));
            }

            return(result);
        }
        private MetadataLoadedInfo LoadMetadata()
        {
            HashSet <ModuleDesc> metadataModules          = new HashSet <ModuleDesc>();
            MetadataType         typeWithMetadataMappings = (MetadataType)_metadataDescribingModule.GetTypeByCustomAttributeTypeName(MetadataMappingTypeName);

            MethodDesc fullMetadataMethod           = typeWithMetadataMappings.GetMethod("Metadata", null);
            MethodDesc weakMetadataMethod           = typeWithMetadataMappings.GetMethod("WeakMetadata", null);
            MethodDesc requiredGenericTypesMethod   = typeWithMetadataMappings.GetMethod("RequiredGenericTypes", null);
            MethodDesc requiredGenericMethodsMethod = typeWithMetadataMappings.GetMethod("RequiredGenericMethods", null);
            MethodDesc requiredGenericFieldsMethod  = typeWithMetadataMappings.GetMethod("RequiredGenericFields", null);
            MethodDesc requiredTemplatesMethod      = typeWithMetadataMappings.GetMethod("CompilerDeterminedInstantiations", null);

            ILProvider ilProvider = new ILProvider(null);

            MetadataLoadedInfo result = new MetadataLoadedInfo();

            if (fullMetadataMethod != null)
            {
                MethodIL fullMethodIL = ilProvider.GetMethodIL(fullMetadataMethod);
                ReadMetadataMethod(fullMethodIL, result.AllTypeMappings, result.MethodMappings, result.FieldMappings, metadataModules);
                foreach (var mapping in result.AllTypeMappings)
                {
                    result.TypesWithStrongMetadataMappings.Add(mapping.Key);
                }
            }

            if (weakMetadataMethod != null)
            {
                MethodIL weakMethodIL = ilProvider.GetMethodIL(weakMetadataMethod);
                Dictionary <MethodDesc, int> weakMethodMappings = new Dictionary <MethodDesc, int>();
                Dictionary <FieldDesc, int>  weakFieldMappings  = new Dictionary <FieldDesc, int>();
                ReadMetadataMethod(weakMethodIL, result.AllTypeMappings, weakMethodMappings, weakFieldMappings, metadataModules);
                if ((weakMethodMappings.Count > 0) || (weakFieldMappings.Count > 0))
                {
                    // the format does not permit weak field/method mappings
                    throw new BadImageFormatException();
                }
            }

            if (requiredGenericTypesMethod != null)
            {
                foreach (var type in ReadRequiredGenericsEntities(ilProvider.GetMethodIL(requiredGenericTypesMethod)))
                {
                    Debug.Assert(type is DefType);
                    result.RequiredGenericTypes.Add((TypeDesc)type);
                }
            }

            if (requiredGenericMethodsMethod != null)
            {
                foreach (var method in ReadRequiredGenericsEntities(ilProvider.GetMethodIL(requiredGenericMethodsMethod)))
                {
                    result.RequiredGenericMethods.Add((MethodDesc)method);
                }
            }

            if (requiredGenericFieldsMethod != null)
            {
                foreach (var field in ReadRequiredGenericsEntities(ilProvider.GetMethodIL(requiredGenericFieldsMethod)))
                {
                    result.RequiredGenericFields.Add((FieldDesc)field);
                }
            }

            if (requiredTemplatesMethod != null)
            {
                ReadRequiredTemplates(ilProvider.GetMethodIL(requiredTemplatesMethod),
                                      result.RequiredTemplateTypes,
                                      result.RequiredTemplateMethods,
                                      result.RequiredTemplateFields);
            }

            result.MetadataModules = ImmutableArray.CreateRange(metadataModules);

            ImmutableArray <ModuleDesc> .Builder externalMetadataModulesBuilder = ImmutableArray.CreateBuilder <ModuleDesc>();
            ImmutableArray <ModuleDesc> .Builder localMetadataModulesBuilder    = ImmutableArray.CreateBuilder <ModuleDesc>();
            foreach (ModuleDesc module in result.MetadataModules)
            {
                if (!_compilationModules.Contains(module))
                {
                    externalMetadataModulesBuilder.Add(module);
                }
                else
                {
                    localMetadataModulesBuilder.Add(module);
                }
            }
            result.ExternalMetadataModules = externalMetadataModulesBuilder.ToImmutable();
            result.LocalMetadataModules    = localMetadataModulesBuilder.ToImmutable();

            foreach (var pair in result.MethodMappings)
            {
                MethodDesc reflectableMethod = pair.Key;

                if (reflectableMethod.HasInstantiation)
                {
                    continue;
                }

                if (reflectableMethod.OwningType.HasInstantiation)
                {
                    continue;
                }

                MethodDesc typicalDynamicInvokeStub;
                if (!_dynamicInvokeStubs.Value.TryGetValue(reflectableMethod, out typicalDynamicInvokeStub))
                {
                    continue;
                }

                MethodDesc instantiatiatedDynamicInvokeStub = InstantiateCanonicalDynamicInvokeMethodForMethod(typicalDynamicInvokeStub, reflectableMethod);
                result.DynamicInvokeCompiledMethods.Add(instantiatiatedDynamicInvokeStub);
            }

            foreach (var reflectableMethod in result.RequiredGenericMethods)
            {
                MethodDesc typicalDynamicInvokeStub;
                if (!_dynamicInvokeStubs.Value.TryGetValue(reflectableMethod.GetTypicalMethodDefinition(), out typicalDynamicInvokeStub))
                {
                    continue;
                }

                MethodDesc instantiatiatedDynamicInvokeStub = InstantiateCanonicalDynamicInvokeMethodForMethod(typicalDynamicInvokeStub, reflectableMethod);
                result.DynamicInvokeCompiledMethods.Add(instantiatiatedDynamicInvokeStub);
            }

            return(result);
        }
        private MetadataLoadedInfo LoadMetadata()
        {
            HashSet <ModuleDesc> metadataModules          = new HashSet <ModuleDesc>();
            MetadataType         typeWithMetadataMappings = (MetadataType)_metadataDescribingModule.GetTypeByCustomAttributeTypeName(MetadataMappingTypeName);

            MethodDesc fullMetadataMethod = typeWithMetadataMappings.GetMethod("Metadata", null);
            MethodDesc weakMetadataMethod = typeWithMetadataMappings.GetMethod("WeakMetadata", null);

            ILProvider ilProvider = new ILProvider(null);

            MetadataLoadedInfo result = new MetadataLoadedInfo();

            if (fullMetadataMethod != null)
            {
                MethodIL fullMethodIL = ilProvider.GetMethodIL(fullMetadataMethod);
                ReadMetadataMethod(fullMethodIL, out result.StrongTypeMappings, out result.MethodMappings, out result.FieldMappings, ref metadataModules);
            }

            if (weakMetadataMethod != null)
            {
                MethodIL weakMethodIL = ilProvider.GetMethodIL(weakMetadataMethod);
                List <MetadataMapping <MethodDesc> > weakMethodMappings = new List <MetadataMapping <MethodDesc> >();
                List <MetadataMapping <FieldDesc> >  weakFieldMappings  = new List <MetadataMapping <FieldDesc> >();
                ReadMetadataMethod(weakMethodIL, out result.AllTypeMappings, out weakMethodMappings, out weakFieldMappings, ref metadataModules);
                if ((weakMethodMappings.Count > 0) || (weakFieldMappings.Count > 0))
                {
                    // the format does not permit weak field/method mappings
                    throw new BadImageFormatException();
                }
            }

#if DEBUG
            // No duplicates are permitted in metadata mappings
            HashSet <TypeSystemEntity> mappingsDuplicateChecker = new HashSet <TypeSystemEntity>();
            foreach (MetadataMapping <MetadataType> mapping in result.AllTypeMappings)
            {
                if (!mappingsDuplicateChecker.Add(mapping.Entity))
                {
                    throw new BadImageFormatException();
                }
            }

            foreach (MetadataMapping <MetadataType> mapping in result.StrongTypeMappings)
            {
                if (!mappingsDuplicateChecker.Add(mapping.Entity))
                {
                    throw new BadImageFormatException();
                }
            }

            foreach (MetadataMapping <FieldDesc> mapping in result.FieldMappings)
            {
                if (!mappingsDuplicateChecker.Add(mapping.Entity))
                {
                    throw new BadImageFormatException();
                }
            }

            foreach (MetadataMapping <MethodDesc> mapping in result.MethodMappings)
            {
                if (!mappingsDuplicateChecker.Add(mapping.Entity))
                {
                    throw new BadImageFormatException();
                }
            }
#endif

            // All type mappings is the combination of strong and weak type mappings.
            result.AllTypeMappings.AddRange(result.StrongTypeMappings);

            result.MetadataModules = ImmutableArray.CreateRange(metadataModules);

            ImmutableArray <ModuleDesc> .Builder externalMetadataModulesBuilder = ImmutableArray.CreateBuilder <ModuleDesc>();
            ImmutableArray <ModuleDesc> .Builder localMetadataModulesBuilder    = ImmutableArray.CreateBuilder <ModuleDesc>();
            foreach (ModuleDesc module in result.MetadataModules)
            {
                if (!_compilationModules.Contains(module))
                {
                    externalMetadataModulesBuilder.Add(module);
                }
                else
                {
                    localMetadataModulesBuilder.Add(module);
                }
            }
            result.ExternalMetadataModules = externalMetadataModulesBuilder.ToImmutable();
            result.LocalMetadataModules    = localMetadataModulesBuilder.ToImmutable();

            return(result);
        }
示例#13
0
            internal TypeCache(MetadataType type, Logger?logger, ILProvider ilProvider)
            {
                Debug.Assert(type == type.GetTypeDefinition());
                Debug.Assert(!CompilerGeneratedNames.IsGeneratedMemberName(type.Name));

                Type = type;

                var callGraph          = new CompilerGeneratedCallGraph();
                var userDefinedMethods = new HashSet <MethodDesc>();

                void ProcessMethod(MethodDesc method)
                {
                    Debug.Assert(method == method.GetTypicalMethodDefinition());

                    bool isStateMachineMember = CompilerGeneratedNames.IsStateMachineType(((MetadataType)method.OwningType).Name);

                    if (!CompilerGeneratedNames.IsLambdaOrLocalFunction(method.Name))
                    {
                        if (!isStateMachineMember)
                        {
                            // If it's not a nested function, track as an entry point to the call graph.
                            var added = userDefinedMethods.Add(method);
                            Debug.Assert(added);
                        }
                    }
                    else
                    {
                        // We don't expect lambdas or local functions to be emitted directly into
                        // state machine types.
                        Debug.Assert(!isStateMachineMember);
                    }

                    // Discover calls or references to lambdas or local functions. This includes
                    // calls to local functions, and lambda assignments (which use ldftn).
                    var methodBody = ilProvider.GetMethodIL(method);

                    if (methodBody != null)
                    {
                        ILReader reader = new ILReader(methodBody.GetILBytes());
                        while (reader.HasNext)
                        {
                            ILOpcode opcode = reader.ReadILOpcode();
                            switch (opcode)
                            {
                            case ILOpcode.ldftn:
                            case ILOpcode.ldtoken:
                            case ILOpcode.call:
                            case ILOpcode.callvirt:
                            case ILOpcode.newobj:
                            {
                                MethodDesc?referencedMethod = methodBody.GetObject(reader.ReadILToken(), NotFoundBehavior.ReturnNull) as MethodDesc;
                                if (referencedMethod == null)
                                {
                                    continue;
                                }

                                referencedMethod = referencedMethod.GetTypicalMethodDefinition();

                                if (referencedMethod.IsConstructor &&
                                    referencedMethod.OwningType is MetadataType generatedType &&
                                    // Don't consider calls in the same type, like inside a static constructor
                                    method.OwningType != generatedType &&
                                    CompilerGeneratedNames.IsLambdaDisplayClass(generatedType.Name))
                                {
                                    Debug.Assert(generatedType.IsTypeDefinition);

                                    // fill in null for now, attribute providers will be filled in later
                                    _generatedTypeToTypeArgumentInfo ??= new Dictionary <MetadataType, TypeArgumentInfo>();

                                    if (!_generatedTypeToTypeArgumentInfo.TryAdd(generatedType, new TypeArgumentInfo(method, null)))
                                    {
                                        var alreadyAssociatedMethod = _generatedTypeToTypeArgumentInfo[generatedType].CreatingMethod;
                                        logger?.LogWarning(new MessageOrigin(method), DiagnosticId.MethodsAreAssociatedWithUserMethod, method.GetDisplayName(), alreadyAssociatedMethod.GetDisplayName(), generatedType.GetDisplayName());
                                    }
                                    continue;
                                }

                                if (!CompilerGeneratedNames.IsLambdaOrLocalFunction(referencedMethod.Name))
                                {
                                    continue;
                                }

                                if (isStateMachineMember)
                                {
                                    callGraph.TrackCall((MetadataType)method.OwningType, referencedMethod);
                                }
                                else
                                {
                                    callGraph.TrackCall(method, referencedMethod);
                                }
                            }
                            break;

                            case ILOpcode.stsfld:
                            {
                                // Same as above, but stsfld instead of a call to the constructor
                                FieldDesc?field = methodBody.GetObject(reader.ReadILToken()) as FieldDesc;
                                if (field == null)
                                {
                                    continue;
                                }

                                field = field.GetTypicalFieldDefinition();

                                if (field.OwningType is MetadataType generatedType &&
                                    // Don't consider field accesses in the same type, like inside a static constructor
                                    method.OwningType != generatedType &&
                                    CompilerGeneratedNames.IsLambdaDisplayClass(generatedType.Name))
                                {
                                    Debug.Assert(generatedType.IsTypeDefinition);

                                    _generatedTypeToTypeArgumentInfo ??= new Dictionary <MetadataType, TypeArgumentInfo>();

                                    if (!_generatedTypeToTypeArgumentInfo.TryAdd(generatedType, new TypeArgumentInfo(method, null)))
                                    {
                                        // It's expected that there may be multiple methods associated with the same static closure environment.
                                        // All of these methods will substitute the same type arguments into the closure environment
                                        // (if it is generic). Don't warn.
                                    }
                                    continue;
                                }
                            }
                            break;

                            default:
                                reader.Skip(opcode);
                                break;
                            }
                        }
                    }

                    if (TryGetStateMachineType(method, out MetadataType? stateMachineType))
                    {
                        Debug.Assert(stateMachineType.ContainingType == type ||
                                     (CompilerGeneratedNames.IsGeneratedMemberName(stateMachineType.ContainingType.Name) &&
                                      stateMachineType.ContainingType.ContainingType == type));
                        Debug.Assert(stateMachineType == stateMachineType.GetTypeDefinition());

                        callGraph.TrackCall(method, stateMachineType);

                        _compilerGeneratedTypeToUserCodeMethod ??= new Dictionary <MetadataType, MethodDesc>();
                        if (!_compilerGeneratedTypeToUserCodeMethod.TryAdd(stateMachineType, method))
                        {
                            var alreadyAssociatedMethod = _compilerGeneratedTypeToUserCodeMethod[stateMachineType];
                            logger?.LogWarning(new MessageOrigin(method), DiagnosticId.MethodsAreAssociatedWithStateMachine, method.GetDisplayName(), alreadyAssociatedMethod.GetDisplayName(), stateMachineType.GetDisplayName());
                        }
                        // Already warned above if multiple methods map to the same type
                        // Fill in null for argument providers now, the real providers will be filled in later
                        _generatedTypeToTypeArgumentInfo ??= new Dictionary <MetadataType, TypeArgumentInfo>();
                        _generatedTypeToTypeArgumentInfo[stateMachineType] = new TypeArgumentInfo(method, null);
                    }
                }

                // Look for state machine methods, and methods which call local functions.
                foreach (MethodDesc method in type.GetMethods())
                {
                    ProcessMethod(method);
                }

                // Also scan compiler-generated state machine methods (in case they have calls to nested functions),
                // and nested functions inside compiler-generated closures (in case they call other nested functions).

                // State machines can be emitted into lambda display classes, so we need to go down at least two
                // levels to find calls from iterator nested functions to other nested functions. We just recurse into
                // all compiler-generated nested types to avoid depending on implementation details.

                foreach (var nestedType in GetCompilerGeneratedNestedTypes(type))
                {
                    foreach (var method in nestedType.GetMethods())
                    {
                        ProcessMethod(method);
                    }
                }

                // Now we've discovered the call graphs for calls to nested functions.
                // Use this to map back from nested functions to the declaring user methods.

                // Note: This maps all nested functions back to the user code, not to the immediately
                // declaring local function. The IL doesn't contain enough information in general for
                // us to determine the nesting of local functions and lambdas.

                // Note: this only discovers nested functions which are referenced from the user
                // code or its referenced nested functions. There is no reliable way to determine from
                // IL which user code an unused nested function belongs to.

                foreach (var userDefinedMethod in userDefinedMethods)
                {
                    var callees = callGraph.GetReachableMembers(userDefinedMethod);
                    if (!callees.Any())
                    {
                        continue;
                    }

                    _compilerGeneratedMembers ??= new Dictionary <MethodDesc, List <TypeSystemEntity> >();
                    _compilerGeneratedMembers.Add(userDefinedMethod, new List <TypeSystemEntity>(callees));

                    foreach (var compilerGeneratedMember in callees)
                    {
                        switch (compilerGeneratedMember)
                        {
                        case MethodDesc nestedFunction:
                            Debug.Assert(CompilerGeneratedNames.IsLambdaOrLocalFunction(nestedFunction.Name));
                            // Nested functions get suppressions from the user method only.
                            _compilerGeneratedMethodToUserCodeMethod ??= new Dictionary <MethodDesc, MethodDesc>();
                            if (!_compilerGeneratedMethodToUserCodeMethod.TryAdd(nestedFunction, userDefinedMethod))
                            {
                                var alreadyAssociatedMethod = _compilerGeneratedMethodToUserCodeMethod[nestedFunction];
                                logger?.LogWarning(new MessageOrigin(userDefinedMethod), DiagnosticId.MethodsAreAssociatedWithUserMethod, userDefinedMethod.GetDisplayName(), alreadyAssociatedMethod.GetDisplayName(), nestedFunction.GetDisplayName());
                            }
                            break;

                        case MetadataType stateMachineType:
                            // Types in the call graph are always state machine types
                            // For those all their methods are not tracked explicitly in the call graph; instead, they
                            // are represented by the state machine type itself.
                            // We are already tracking the association of the state machine type to the user code method
                            // above, so no need to track it here.
                            Debug.Assert(CompilerGeneratedNames.IsStateMachineType(stateMachineType.Name));
                            break;

                        default:
                            throw new InvalidOperationException();
                        }
                    }
                }

                // Now that we have instantiating methods fully filled out, walk the generated types and fill in the attribute
                // providers
                if (_generatedTypeToTypeArgumentInfo != null)
                {
                    foreach (var generatedType in _generatedTypeToTypeArgumentInfo.Keys)
                    {
                        Debug.Assert(generatedType == generatedType.GetTypeDefinition());

                        if (HasGenericParameters(generatedType))
                        {
                            MapGeneratedTypeTypeParameters(generatedType);
                        }
                    }
                }
示例#14
0
 internal MethodIL GetMethodIL(MethodDesc method)
 {
     return(_ilProvider.GetMethodIL(method));
 }
示例#15
0
 public MethodIL GetMethodIL(MethodDesc method)
 {
     return(_ilProvider.GetMethodIL(method));
 }