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(); } }
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)); }
public MethodIL GetMethodIL(MethodDesc method) { // Flush the cache when it grows too big if (_methodILCache.Count > 1000) { _methodILCache = new ILProvider(); } return(_methodILCache.GetMethodIL(method)); }
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)); }
public override MethodIL GetMethodIL(MethodDesc method) { MethodIL result = _primaryILProvider.GetMethodIL(method); if (result == null && method.IsPInvoke) { result = _pinvokeProvider.GetMethodIL(method); } return(result); }
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); }
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 }
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); }
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); } } }
internal MethodIL GetMethodIL(MethodDesc method) { return(_ilProvider.GetMethodIL(method)); }
public MethodIL GetMethodIL(MethodDesc method) { return(_ilProvider.GetMethodIL(method)); }