From 107fe5eb1c9f5a268eee853143fac0cb24e2c5d1 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 14 Jul 2018 14:18:54 +0200 Subject: [PATCH] Eliminate SpecializingDecompilerTypeSystem and use GenericContext instead. --- ICSharpCode.Decompiler.Tests/DataFlowTest.cs | 2 +- .../CSharp/CSharpDecompiler.cs | 14 +- .../CSharp/ExpressionBuilder.cs | 3 +- .../CSharp/Syntax/TypeSystemAstBuilder.cs | 11 +- .../ICSharpCode.Decompiler.csproj | 1 - ICSharpCode.Decompiler/IL/BlockBuilder.cs | 13 +- .../IL/ControlFlow/YieldReturnDecompiler.cs | 22 ++-- ICSharpCode.Decompiler/IL/ILReader.cs | 89 ++++++++----- .../IL/Instructions/ILFunction.cs | 12 +- .../IL/Transforms/DelegateConstruction.cs | 37 +++++- .../IL/Transforms/IILTransform.cs | 10 +- .../IL/Transforms/ProxyCallReplacer.cs | 13 +- .../IL/Transforms/TransformExpressionTrees.cs | 3 +- ICSharpCode.Decompiler/NRExtensions.cs | 18 --- .../TypeSystem/DecompilerTypeSystem.cs | 9 -- .../TypeSystem/IDecompilerTypeSystem.cs | 6 - .../Implementation/SpecializedParameter.cs | 5 + .../TypeSystem/MetadataModule.cs | 80 ++++++++--- .../SpecializingDecompilerTypeSystem.cs | 124 ------------------ .../TypeSystem/TypeParameterSubstitution.cs | 8 ++ .../ConnectMethodDecompiler.cs | 11 +- ILSpy/Languages/ILAstLanguage.cs | 9 +- 22 files changed, 223 insertions(+), 277 deletions(-) delete mode 100644 ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs diff --git a/ICSharpCode.Decompiler.Tests/DataFlowTest.cs b/ICSharpCode.Decompiler.Tests/DataFlowTest.cs index d46f465e5..3c599ccc2 100644 --- a/ICSharpCode.Decompiler.Tests/DataFlowTest.cs +++ b/ICSharpCode.Decompiler.Tests/DataFlowTest.cs @@ -55,7 +55,7 @@ namespace ICSharpCode.Decompiler.Tests public void TryFinallyWithAssignmentInFinally() { ILVariable v = new ILVariable(VariableKind.Local, SpecialType.UnknownType, 0); - ILFunction f = new ILFunction((IMethod)null, 0, new TryFinally( + ILFunction f = new ILFunction((IMethod)null, 0, new GenericContext(), new TryFinally( new Nop(), new StLoc(v, new LdcI4(0)) )); diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index e9b5e99e0..26d5bd0d3 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -1001,14 +1001,14 @@ namespace ICSharpCode.Decompiler.CSharp void DecompileBody(IMethod method, EntityDeclaration entityDecl, DecompileRun decompileRun, ITypeResolveContext decompilationContext) { try { - var specializingTypeSystem = typeSystem.GetSpecializingTypeSystem(decompilationContext); - var ilReader = new ILReader(specializingTypeSystem) { + var ilReader = new ILReader(typeSystem.MainModule) { UseDebugSymbols = settings.UseDebugSymbols, DebugInfo = DebugInfoProvider }; + var genericContext = new Decompiler.TypeSystem.GenericContext(decompilationContext); var methodDef = typeSystem.ModuleDefinition.Metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken); var methodBody = typeSystem.ModuleDefinition.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); - var function = ilReader.ReadIL(typeSystem.ModuleDefinition, (MethodDefinitionHandle)method.MetadataToken, methodBody, CancellationToken); + var function = ilReader.ReadIL((MethodDefinitionHandle)method.MetadataToken, methodBody, genericContext, CancellationToken); function.CheckInvariant(ILPhase.Normal); if (entityDecl != null) { @@ -1029,7 +1029,7 @@ namespace ICSharpCode.Decompiler.CSharp localSettings.AlwaysCastTargetsOfExplicitInterfaceImplementationCalls = true; } - var context = new ILTransformContext(function, specializingTypeSystem, DebugInfoProvider, localSettings) { + var context = new ILTransformContext(function, typeSystem, DebugInfoProvider, localSettings) { CancellationToken = CancellationToken, DecompileRun = decompileRun }; @@ -1047,8 +1047,8 @@ namespace ICSharpCode.Decompiler.CSharp var body = BlockStatement.Null; // Generate C# AST only if bodies should be displayed. if (localSettings.DecompileMemberBodies) { - AddDefinesForConditionalAttributes(function, decompileRun, decompilationContext); - var statementBuilder = new StatementBuilder(specializingTypeSystem, decompilationContext, function, localSettings, CancellationToken); + AddDefinesForConditionalAttributes(function, decompileRun); + var statementBuilder = new StatementBuilder(typeSystem, decompilationContext, function, localSettings, CancellationToken); body = statementBuilder.ConvertAsBlock(function.Body); Comment prev = null; @@ -1112,7 +1112,7 @@ namespace ICSharpCode.Decompiler.CSharp return false; } - void AddDefinesForConditionalAttributes(ILFunction function, DecompileRun decompileRun, ITypeResolveContext decompilationContext) + void AddDefinesForConditionalAttributes(ILFunction function, DecompileRun decompileRun) { foreach (var call in function.Descendants.OfType()) { var attr = call.Method.GetAttribute(KnownAttribute.Conditional, inherit: true); diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 0fba9c7f3..45098bf30 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -1491,8 +1491,7 @@ namespace ICSharpCode.Decompiler.CSharp ame.IsAsync = function.IsAsync; ame.Parameters.AddRange(MakeParameters(function.Parameters, function)); ame.HasParameterList = ame.Parameters.Count > 0; - var targetTS = method == null ? typeSystem : typeSystem.GetSpecializingTypeSystem(method.Substitution); - StatementBuilder builder = new StatementBuilder(targetTS, this.decompilationContext, function, settings, cancellationToken); + StatementBuilder builder = new StatementBuilder(typeSystem, this.decompilationContext, function, settings, cancellationToken); var body = builder.ConvertAsBlock(function.Body); Comment prev = null; diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs index 51964a4cf..46e2f91ee 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs @@ -476,11 +476,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax var p = (i < parameters.Count) ? parameters[i] : null; attr.Arguments.Add(ConvertConstantValue(p?.Type ?? arg.Type, arg.Type, arg.Value)); } - if (attribute.HasDecodeErrors) { - attr.HasArgumentList = true; - attr.AddChild(new Comment("Could not decode attribute arguments.", CommentType.MultiLine), Roles.Comment); - attr.AddChild(new CSharpTokenNode(TextLocation.Empty, Roles.RPar), Roles.RPar); - } if (attribute.NamedArguments.Length > 0) { InitializedObjectResolveResult targetResult = new InitializedObjectResolveResult(attribute.AttributeType); foreach (var namedArg in attribute.NamedArguments) { @@ -494,6 +489,12 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax attr.Arguments.Add(namedArgument); } } + if (attribute.HasDecodeErrors) { + attr.HasArgumentList = true; + attr.AddChild(new Comment("Could not decode attribute arguments.", CommentType.MultiLine), Roles.Comment); + // insert explicit rpar token to make the comment appear within the parentheses + attr.AddChild(new CSharpTokenNode(TextLocation.Empty, Roles.RPar), Roles.RPar); + } return attr; } diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index 4826a9bab..10a88b460 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -547,7 +547,6 @@ - diff --git a/ICSharpCode.Decompiler/IL/BlockBuilder.cs b/ICSharpCode.Decompiler/IL/BlockBuilder.cs index b002dcaf3..bc732b887 100644 --- a/ICSharpCode.Decompiler/IL/BlockBuilder.cs +++ b/ICSharpCode.Decompiler/IL/BlockBuilder.cs @@ -21,17 +21,16 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; +using System.Reflection.Metadata; using System.Threading; -using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; namespace ICSharpCode.Decompiler.IL { class BlockBuilder { - readonly System.Reflection.Metadata.MethodBodyBlock body; - readonly IDecompilerTypeSystem typeSystem; - readonly Dictionary variableByExceptionHandler; + readonly MethodBodyBlock body; + readonly Dictionary variableByExceptionHandler; /// /// Gets/Sets whether to create extended basic blocks instead of basic blocks. @@ -39,14 +38,12 @@ namespace ICSharpCode.Decompiler.IL /// public bool CreateExtendedBlocks; - internal BlockBuilder(System.Reflection.Metadata.MethodBodyBlock body, IDecompilerTypeSystem typeSystem, - Dictionary variableByExceptionHandler) + internal BlockBuilder(MethodBodyBlock body, + Dictionary variableByExceptionHandler) { Debug.Assert(body != null); - Debug.Assert(typeSystem != null); Debug.Assert(variableByExceptionHandler != null); this.body = body; - this.typeSystem = typeSystem; this.variableByExceptionHandler = variableByExceptionHandler; } diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs b/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs index 408844da6..0986592d3 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs @@ -373,20 +373,14 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow if (!methodDef.HasBody()) throw new SymbolicAnalysisFailedException(); - var sdtp = typeSystem as SpecializingDecompilerTypeSystem; - if (sdtp != null) { - typeSystem = new SpecializingDecompilerTypeSystem( - sdtp.Context, - new TypeParameterSubstitution( - (sdtp.Substitution.ClassTypeArguments ?? EmptyList.Instance) - .Concat(sdtp.Substitution.MethodTypeArguments ?? EmptyList.Instance).ToArray(), - EmptyList.Instance - ) - ); - } - var body = typeSystem.ModuleDefinition.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); - var il = context.CreateILReader(typeSystem) - .ReadIL(typeSystem.ModuleDefinition, method, body, context.CancellationToken); + GenericContext genericContext = context.Function.GenericContext; + genericContext = new GenericContext( + classTypeParameters: (genericContext.ClassTypeParameters ?? EmptyList.Instance) + .Concat(genericContext.MethodTypeParameters ?? EmptyList.Instance).ToArray(), + methodTypeParameters: null); + var body = context.TypeSystem.MainModule.PEFile.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); + var il = context.CreateILReader() + .ReadIL(method, body, genericContext, context.CancellationToken); il.RunTransforms(CSharpDecompiler.EarlyILTransforms(true), new ILTransformContext(il, typeSystem, context.DebugInfo, context.Settings) { CancellationToken = context.CancellationToken, diff --git a/ICSharpCode.Decompiler/IL/ILReader.cs b/ICSharpCode.Decompiler/IL/ILReader.cs index c7d544ba9..13338be68 100644 --- a/ICSharpCode.Decompiler/IL/ILReader.cs +++ b/ICSharpCode.Decompiler/IL/ILReader.cs @@ -34,24 +34,38 @@ using System.Reflection.Metadata.Ecma335; namespace ICSharpCode.Decompiler.IL { + /// + /// Reads IL bytecodes and converts them into ILAst instructions. + /// + /// + /// Instances of this class are not thread-safe. Use separate instances to decompile multiple members in parallel. + /// public class ILReader { readonly ICompilation compilation; - readonly IDecompilerTypeSystem typeSystem; + readonly MetadataModule module; + readonly MetadataReader metadata; public bool UseDebugSymbols { get; set; } public DebugInfo.IDebugInfoProvider DebugInfo { get; set; } public List Warnings { get; } = new List(); - public ILReader(IDecompilerTypeSystem typeSystem) + /// + /// Creates a new ILReader instance. + /// + /// + /// The module used to resolve metadata tokens in the type system. + /// + public ILReader(MetadataModule module) { - if (typeSystem == null) - throw new ArgumentNullException(nameof(typeSystem)); - this.typeSystem = typeSystem; - this.compilation = typeSystem.Compilation; + if (module == null) + throw new ArgumentNullException(nameof(module)); + this.module = module; + this.compilation = module.Compilation; + this.metadata = module.metadata; } - MetadataReader metadata; + GenericContext genericContext; IMethod method; MethodBodyBlock body; StackType methodReturnStackType; @@ -70,12 +84,23 @@ namespace ICSharpCode.Decompiler.IL List<(ILVariable, ILVariable)> stackMismatchPairs; IEnumerable stackVariables; - void Init(Metadata.PEFile module, MethodDefinitionHandle methodDefinitionHandle, MethodBodyBlock body) + void Init(MethodDefinitionHandle methodDefinitionHandle, MethodBodyBlock body, GenericContext genericContext) { if (body == null) throw new ArgumentNullException(nameof(body)); - this.metadata = module.Metadata; - this.method = typeSystem.ResolveAsMethod(methodDefinitionHandle); + if (methodDefinitionHandle.IsNil) + throw new ArgumentException("methodDefinitionHandle.IsNil"); + this.method = module.GetDefinition(methodDefinitionHandle); + if (genericContext.ClassTypeParameters == null && genericContext.MethodTypeParameters == null) { + if (method.DeclaringType.TypeParameterCount > 0 || method.TypeParameters.Count > 0) { + // no generic context specified, but it's a generic method: use the method's own type parameters + genericContext = new GenericContext(method); + } + } else { + // generic context specified, so specialize the method for it: + this.method = this.method.Specialize(new TypeParameterSubstitution(genericContext.ClassTypeParameters, genericContext.MethodTypeParameters)); + } + this.genericContext = genericContext; var methodDefinition = metadata.GetMethodDefinition(methodDefinitionHandle); this.body = body; this.reader = body.GetILReader(); @@ -111,22 +136,19 @@ namespace ICSharpCode.Decompiler.IL IType ReadAndDecodeTypeReference() { var typeReference = ReadAndDecodeMetadataToken(); - return typeSystem.ResolveAsType(typeReference); + return module.ResolveType(typeReference, genericContext); } IMethod ReadAndDecodeMethodReference() { var methodReference = ReadAndDecodeMetadataToken(); - IMethod m = typeSystem.ResolveAsMethod(methodReference); - if (m == null) - throw new BadImageFormatException("Invalid method token"); - return m; + return module.ResolveMethod(methodReference, genericContext); } IField ReadAndDecodeFieldReference() { var fieldReference = ReadAndDecodeMetadataToken(); - IField f = typeSystem.ResolveAsField(fieldReference); + var f = module.ResolveEntity(fieldReference, genericContext) as IField; if (f == null) throw new BadImageFormatException("Invalid field token"); return f; @@ -135,7 +157,7 @@ namespace ICSharpCode.Decompiler.IL ILVariable[] InitLocalVariables() { if (body.LocalSignature.IsNil) return Empty.Array; - var variableTypes = typeSystem.DecodeLocalSignature(body.LocalSignature); + var variableTypes = module.DecodeLocalSignature(body.LocalSignature, genericContext); var localVariables = new ILVariable[variableTypes.Length]; foreach (var (index, type) in variableTypes.WithIndex()) { localVariables[index] = CreateILVariable(index, type); @@ -317,14 +339,15 @@ namespace ICSharpCode.Decompiler.IL foreach (var eh in body.ExceptionRegions) { ImmutableStack ehStack = null; if (eh.Kind == ExceptionRegionKind.Catch) { - var v = new ILVariable(VariableKind.Exception, typeSystem.ResolveAsType(eh.CatchType), eh.HandlerOffset) { + var catchType = module.ResolveType(eh.CatchType, genericContext); + var v = new ILVariable(VariableKind.Exception, catchType, eh.HandlerOffset) { Name = "E_" + eh.HandlerOffset, HasGeneratedName = true }; variableByExceptionHandler.Add(eh, v); ehStack = ImmutableStack.Create(v); } else if (eh.Kind == ExceptionRegionKind.Filter) { - var v = new ILVariable(VariableKind.Exception, typeSystem.Compilation.FindType(KnownTypeCode.Object), eh.HandlerOffset) { + var v = new ILVariable(VariableKind.Exception, compilation.FindType(KnownTypeCode.Object), eh.HandlerOffset) { Name = "E_" + eh.HandlerOffset, HasGeneratedName = true }; @@ -409,10 +432,10 @@ namespace ICSharpCode.Decompiler.IL /// /// Debugging helper: writes the decoded instruction stream interleaved with the inferred evaluation stack layout. /// - public void WriteTypedIL(Metadata.PEFile module, - MethodDefinitionHandle method, MethodBodyBlock body, ITextOutput output, CancellationToken cancellationToken = default) + public void WriteTypedIL(MethodDefinitionHandle method, MethodBodyBlock body, + ITextOutput output, GenericContext genericContext = default, CancellationToken cancellationToken = default) { - Init(module, method, body); + Init(method, body, genericContext); ReadInstructions(cancellationToken); foreach (var inst in instructionBuilder) { if (inst is StLoc stloc && stloc.IsStackAdjustment) { @@ -444,21 +467,20 @@ namespace ICSharpCode.Decompiler.IL output.WriteLine(); } new Disassembler.MethodBodyDisassembler(output, cancellationToken) { DetectControlStructure = false } - .WriteExceptionHandlers(module, method, body); + .WriteExceptionHandlers(module.PEFile, method, body); } /// /// Decodes the specified method body and returns an ILFunction. /// - public ILFunction ReadIL(Metadata.PEFile module, MethodDefinitionHandle method, MethodBodyBlock body, CancellationToken cancellationToken = default(CancellationToken)) + public ILFunction ReadIL(MethodDefinitionHandle method, MethodBodyBlock body, GenericContext genericContext = default, CancellationToken cancellationToken = default) { cancellationToken.ThrowIfCancellationRequested(); - Init(module, method, body); + Init(method, body, genericContext); ReadInstructions(cancellationToken); - var blockBuilder = new BlockBuilder(body, typeSystem, variableByExceptionHandler); + var blockBuilder = new BlockBuilder(body, variableByExceptionHandler); blockBuilder.CreateBlocks(mainContainer, instructionBuilder, isBranchTarget, cancellationToken); - var resolvedMethod = typeSystem.ResolveAsMethod(method); - var function = new ILFunction(resolvedMethod, body.GetCodeSize(), mainContainer); + var function = new ILFunction(this.method, body.GetCodeSize(), genericContext, mainContainer); CollectionExtensions.AddRange(function.Variables, parameterVariables); CollectionExtensions.AddRange(function.Variables, localVariables); CollectionExtensions.AddRange(function.Variables, stackVariables); @@ -1358,7 +1380,7 @@ namespace ICSharpCode.Decompiler.IL ILInstruction DecodeCallIndirect() { var signatureHandle = (StandaloneSignatureHandle)ReadAndDecodeMetadataToken(); - var signature = typeSystem.DecodeMethodSignature(signatureHandle); + var signature = module.DecodeMethodSignature(signatureHandle, genericContext); var functionPointer = Pop(StackType.I); Debug.Assert(!signature.Header.IsInstance); var arguments = new ILInstruction[signature.ParameterTypes.Length]; @@ -1586,9 +1608,12 @@ namespace ICSharpCode.Decompiler.IL ILInstruction LdToken(EntityHandle token) { if (token.Kind.IsTypeKind()) - return new LdTypeToken(typeSystem.ResolveAsType(token)); - if (token.Kind.IsMemberKind()) - return new LdMemberToken(typeSystem.ResolveAsMember(token)); + return new LdTypeToken(module.ResolveType(token, genericContext)); + if (token.Kind.IsMemberKind()) { + var entity = module.ResolveEntity(token, genericContext); + if (entity is IMember member) + return new LdMemberToken(member); + } throw new BadImageFormatException("Invalid metadata token for ldtoken instruction."); } } diff --git a/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs b/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs index dedffed50..559aaa7e4 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs @@ -29,6 +29,7 @@ namespace ICSharpCode.Decompiler.IL partial class ILFunction { public readonly IMethod Method; + public readonly GenericContext GenericContext; public readonly int CodeSize; public readonly ILVariableCollection Variables; @@ -52,7 +53,7 @@ namespace ICSharpCode.Decompiler.IL /// Gets whether this function is async. /// This flag gets set by the AsyncAwaitDecompiler. /// - public bool IsAsync { get => AsyncReturnType != null; } + public bool IsAsync => AsyncReturnType != null; /// /// Return element type -- if the async method returns Task{T}, this field stores T. @@ -72,17 +73,20 @@ namespace ICSharpCode.Decompiler.IL public readonly IReadOnlyList Parameters; - public ILFunction(IMethod method, int codeSize, ILInstruction body) : base(OpCode.ILFunction) + public ILFunction(IMethod method, int codeSize, GenericContext genericContext, ILInstruction body) : base(OpCode.ILFunction) { - this.Body = body; this.Method = method; + this.CodeSize = codeSize; + this.GenericContext = genericContext; + this.Body = body; this.ReturnType = Method?.ReturnType; this.Parameters = Method?.Parameters; this.Variables = new ILVariableCollection(this); } - public ILFunction(IType returnType, IReadOnlyList parameters, ILInstruction body) : base(OpCode.ILFunction) + public ILFunction(IType returnType, IReadOnlyList parameters, GenericContext genericContext, ILInstruction body) : base(OpCode.ILFunction) { + this.GenericContext = genericContext; this.Body = body; this.ReturnType = returnType; this.Parameters = parameters; diff --git a/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs b/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs index 991d57f33..71fbce258 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs @@ -125,6 +125,29 @@ namespace ICSharpCode.Decompiler.IL.Transforms return true; } + internal static GenericContext? GenericContextFromTypeArguments(TypeParameterSubstitution subst) + { + var classTypeParameters = new List(); + var methodTypeParameters = new List(); + if (subst.ClassTypeArguments != null) { + foreach (var t in subst.ClassTypeArguments) { + if (t is ITypeParameter tp) + classTypeParameters.Add(tp); + else + return null; + } + } + if (subst.MethodTypeArguments != null) { + foreach (var t in subst.MethodTypeArguments) { + if (t is ITypeParameter tp) + classTypeParameters.Add(tp); + else + return null; + } + } + return new GenericContext(classTypeParameters, methodTypeParameters); + } + ILFunction TransformDelegateConstruction(NewObj value, out ILInstruction target) { target = null; @@ -140,9 +163,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms var methodDefinition = metadata.GetMethodDefinition((MethodDefinitionHandle)targetMethod.MetadataToken); if (!methodDefinition.HasBody()) return null; - var localTypeSystem = context.TypeSystem.GetSpecializingTypeSystem(targetMethod.Substitution); - var ilReader = context.CreateILReader(localTypeSystem); - var function = ilReader.ReadIL(context.TypeSystem.ModuleDefinition, (MethodDefinitionHandle)targetMethod.MetadataToken, context.TypeSystem.ModuleDefinition.Reader.GetMethodBody(methodDefinition.RelativeVirtualAddress), context.CancellationToken); + var genericContext = GenericContextFromTypeArguments(targetMethod.Substitution); + if (genericContext == null) + return null; + var ilReader = context.CreateILReader(); + var body = context.TypeSystem.ModuleDefinition.Reader.GetMethodBody(methodDefinition.RelativeVirtualAddress); + var function = ilReader.ReadIL((MethodDefinitionHandle)targetMethod.MetadataToken, body, genericContext.Value, context.CancellationToken); function.DelegateType = value.Method.DeclaringType; function.CheckInvariant(ILPhase.Normal); @@ -151,10 +177,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms v.Name = contextPrefix + v.Name; } - var nestedContext = new ILTransformContext(function, localTypeSystem, context.DebugInfo, context.Settings) { - CancellationToken = context.CancellationToken, - DecompileRun = context.DecompileRun - }; + var nestedContext = new ILTransformContext(context, function); function.RunTransforms(CSharpDecompiler.GetILTransforms().TakeWhile(t => !(t is DelegateConstruction)), nestedContext); function.AcceptVisitor(new ReplaceDelegateTargetVisitor(target, function.Variables.SingleOrDefault(v => v.Index == -1 && v.Kind == VariableKind.Parameter))); // handle nested lambdas diff --git a/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs index a549f07c4..00376aaa1 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs @@ -60,9 +60,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms Stepper = new Stepper(); } - public ILTransformContext(ILTransformContext context) + public ILTransformContext(ILTransformContext context, ILFunction function = null) { - this.Function = context.Function; + this.Function = function ?? context.Function; this.TypeSystem = context.TypeSystem; this.DebugInfo = context.DebugInfo; this.Settings = context.Settings; @@ -71,11 +71,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms this.Stepper = context.Stepper; } - public ILReader CreateILReader(IDecompilerTypeSystem typeSystem = null) + public ILReader CreateILReader() { - if (typeSystem == null) - typeSystem = this.TypeSystem; - return new ILReader(typeSystem) { + return new ILReader(TypeSystem.MainModule) { UseDebugSymbols = Settings.UseDebugSymbols, DebugInfo = DebugInfo }; diff --git a/ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs b/ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs index f2a3c84fb..d89fedd12 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs @@ -29,15 +29,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms MethodDefinition methodDef = metadata.GetMethodDefinition((MethodDefinitionHandle)inst.Method.MetadataToken); if (!methodDef.HasBody()) return; + var genericContext = DelegateConstruction.GenericContextFromTypeArguments(inst.Method.Substitution); + if (genericContext == null) + return; // partially copied from CSharpDecompiler - var specializingTypeSystem = context.TypeSystem.GetSpecializingTypeSystem(inst.Method.Substitution); - var ilReader = context.CreateILReader(specializingTypeSystem); + var ilReader = context.CreateILReader(); var body = module.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); - var proxyFunction = ilReader.ReadIL(module, handle, body, context.CancellationToken); - var transformContext = new ILTransformContext(proxyFunction, specializingTypeSystem, context.DebugInfo, context.Settings) { - CancellationToken = context.CancellationToken, - DecompileRun = context.DecompileRun - }; + var proxyFunction = ilReader.ReadIL(handle, body, genericContext.Value, context.CancellationToken); + var transformContext = new ILTransformContext(context, proxyFunction); proxyFunction.RunTransforms(CSharp.CSharpDecompiler.EarlyILTransforms(), transformContext); if (!(proxyFunction.Body is BlockContainer blockContainer)) return; diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs index 555fc9630..dc712685a 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs @@ -151,7 +151,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms return (null, SpecialType.UnknownType); var container = new BlockContainer(); var functionType = instruction.Method.ReturnType.TypeArguments[0]; - var function = new ILFunction(functionType.GetDelegateInvokeMethod()?.ReturnType, parameterList, container); + var returnType = functionType.GetDelegateInvokeMethod()?.ReturnType; + var function = new ILFunction(returnType, parameterList, context.Function.GenericContext, container); function.DelegateType = functionType; function.Variables.AddRange(parameterVariablesList); lambdaStack.Push(function); diff --git a/ICSharpCode.Decompiler/NRExtensions.cs b/ICSharpCode.Decompiler/NRExtensions.cs index 0a816ad82..30ca90951 100644 --- a/ICSharpCode.Decompiler/NRExtensions.cs +++ b/ICSharpCode.Decompiler/NRExtensions.cs @@ -23,24 +23,6 @@ namespace ICSharpCode.Decompiler { public static class NRExtensions { - public static IDecompilerTypeSystem GetSpecializingTypeSystem(this IDecompilerTypeSystem typeSystem, ITypeResolveContext decompilationContext) - { - IReadOnlyList classTypeParameters = null; - IReadOnlyList methodTypeParameters = null; - - if (decompilationContext.CurrentTypeDefinition != null && decompilationContext.CurrentTypeDefinition.TypeParameterCount > 0) - classTypeParameters = decompilationContext.CurrentTypeDefinition.TypeArguments; - IMethod method = decompilationContext.CurrentMember as IMethod; - if (method != null && method.TypeParameters.Count > 0) - methodTypeParameters = method.TypeArguments; - if (typeSystem is SpecializingDecompilerTypeSystem) - typeSystem = ((SpecializingDecompilerTypeSystem)typeSystem).Context; - if ((classTypeParameters != null && classTypeParameters.Count > 0) || (methodTypeParameters != null && methodTypeParameters.Count > 0)) - return new SpecializingDecompilerTypeSystem(typeSystem, new TypeParameterSubstitution(classTypeParameters, methodTypeParameters)); - else - return typeSystem; - } - public static bool IsCompilerGenerated(this IEntity entity) { if (entity != null) { diff --git a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs index f455f8a7b..39822d7ea 100644 --- a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs +++ b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs @@ -264,14 +264,5 @@ namespace ICSharpCode.Decompiler.TypeSystem return ApplyAttributeTypeVisitor.ApplyAttributesToType(t, compilation, null, moduleDefinition.Metadata, typeSystemOptions); } - - public IDecompilerTypeSystem GetSpecializingTypeSystem(TypeParameterSubstitution substitution) - { - if (substitution.Equals(TypeParameterSubstitution.Identity)) { - return this; - } else { - return new SpecializingDecompilerTypeSystem(this, substitution); - } - } } } diff --git a/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs index ee02d6825..b186e7d6f 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs @@ -40,11 +40,5 @@ namespace ICSharpCode.Decompiler.TypeSystem MetadataReader GetMetadata(); PEFile ModuleDefinition { get; } - - /// - /// Gets a type system instance that automatically specializes the results - /// of each Resolve() call with the provided substitution. - /// - IDecompilerTypeSystem GetSpecializingTypeSystem(TypeParameterSubstitution substitution); } } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedParameter.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedParameter.cs index 5e6070f0a..bca6f3075 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedParameter.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedParameter.cs @@ -47,5 +47,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation bool IVariable.IsConst => baseParameter.IsConst; object IVariable.ConstantValue => baseParameter.ConstantValue; SymbolKind ISymbol.SymbolKind => SymbolKind.Parameter; + + public override string ToString() + { + return DefaultParameter.ToString(this); + } } } diff --git a/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs b/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs index a17271e67..44561040c 100644 --- a/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs +++ b/ICSharpCode.Decompiler/TypeSystem/MetadataModule.cs @@ -170,11 +170,13 @@ namespace ICSharpCode.Decompiler.TypeSystem public ITypeDefinition GetDefinition(TypeDefinitionHandle handle) { + if (handle.IsNil) + return null; int row = MetadataTokens.GetRowNumber(handle); if (row >= typeDefs.Length) - return null; + HandleOutOfRange(handle); var typeDef = LazyInit.VolatileRead(ref typeDefs[row]); - if (typeDef != null || handle.IsNil) + if (typeDef != null) return typeDef; typeDef = new MetadataTypeDefinition(this, handle); return LazyInit.GetOrSet(ref typeDefs[row], typeDef); @@ -182,11 +184,13 @@ namespace ICSharpCode.Decompiler.TypeSystem public IField GetDefinition(FieldDefinitionHandle handle) { + if (handle.IsNil) + return null; int row = MetadataTokens.GetRowNumber(handle); if (row >= fieldDefs.Length) - return null; + HandleOutOfRange(handle); var field = LazyInit.VolatileRead(ref fieldDefs[row]); - if (field != null || handle.IsNil) + if (field != null) return field; field = new MetadataField(this, handle); return LazyInit.GetOrSet(ref fieldDefs[row], field); @@ -194,11 +198,14 @@ namespace ICSharpCode.Decompiler.TypeSystem public IMethod GetDefinition(MethodDefinitionHandle handle) { + if (handle.IsNil) + return null; int row = MetadataTokens.GetRowNumber(handle); + Debug.Assert(row != 0); if (row >= methodDefs.Length) - return null; + HandleOutOfRange(handle); var method = LazyInit.VolatileRead(ref methodDefs[row]); - if (method != null || handle.IsNil) + if (method != null) return method; method = new MetadataMethod(this, handle); return LazyInit.GetOrSet(ref methodDefs[row], method); @@ -206,11 +213,14 @@ namespace ICSharpCode.Decompiler.TypeSystem public IProperty GetDefinition(PropertyDefinitionHandle handle) { + if (handle.IsNil) + return null; int row = MetadataTokens.GetRowNumber(handle); + Debug.Assert(row != 0); if (row >= methodDefs.Length) - return null; + HandleOutOfRange(handle); var property = LazyInit.VolatileRead(ref propertyDefs[row]); - if (property != null || handle.IsNil) + if (property != null) return property; property = new MetadataProperty(this, handle); return LazyInit.GetOrSet(ref propertyDefs[row], property); @@ -218,15 +228,23 @@ namespace ICSharpCode.Decompiler.TypeSystem public IEvent GetDefinition(EventDefinitionHandle handle) { + if (handle.IsNil) + return null; int row = MetadataTokens.GetRowNumber(handle); + Debug.Assert(row != 0); if (row >= methodDefs.Length) - return null; + HandleOutOfRange(handle); var ev = LazyInit.VolatileRead(ref eventDefs[row]); - if (ev != null || handle.IsNil) + if (ev != null) return ev; ev = new MetadataEvent(this, handle); return LazyInit.GetOrSet(ref eventDefs[row], ev); } + + void HandleOutOfRange(EntityHandle handle) + { + throw new BadImageFormatException("Handle with invalid row number."); + } #endregion #region Resolve Type @@ -271,6 +289,12 @@ namespace ICSharpCode.Decompiler.TypeSystem ty = ApplyAttributeTypeVisitor.ApplyAttributesToType(ty, Compilation, null, metadata, options, typeChildrenOnly: true); return ty; } + + IType IntroduceTupleTypes(IType ty) + { + // run ApplyAttributeTypeVisitor without attributes, in order to introduce tuple types + return ApplyAttributeTypeVisitor.ApplyAttributesToType(ty, Compilation, null, metadata, options); + } #endregion #region Resolve Method @@ -293,9 +317,6 @@ namespace ICSharpCode.Decompiler.TypeSystem IMethod ResolveMethodDefinition(MethodDefinitionHandle methodDefHandle, bool expandVarArgs) { var method = GetDefinition(methodDefHandle); - if (method == null) { - throw new BadImageFormatException("MethodDef not found in current assembly."); - } if (expandVarArgs && method.Parameters.LastOrDefault()?.Type.Kind == TypeKind.ArgList) { method = new VarArgInstanceMethod(method, EmptyList.Instance); } @@ -306,13 +327,12 @@ namespace ICSharpCode.Decompiler.TypeSystem { var methodSpec = metadata.GetMethodSpecification(methodSpecHandle); var methodTypeArgs = methodSpec.DecodeSignature(TypeProvider, context) - .SelectReadOnlyArray(ta => ApplyAttributeTypeVisitor.ApplyAttributesToType(ta, Compilation, - methodSpec.GetCustomAttributes(), metadata, this.TypeSystemOptions)); + .SelectReadOnlyArray(IntroduceTupleTypes); IMethod method; if (methodSpec.Method.Kind == HandleKind.MethodDefinition) { // generic instance of a methoddef (=generic method in non-generic class in current assembly) method = ResolveMethodDefinition((MethodDefinitionHandle)methodSpec.Method, expandVarArgs); - method = method.Specialize(new TypeParameterSubstitution(context.ClassTypeParameters, methodTypeArgs)); + method = method.Specialize(new TypeParameterSubstitution(null, methodTypeArgs)); } else { method = ResolveMethodReference((MemberReferenceHandle)methodSpec.Method, context, methodTypeArgs, expandVarArgs); } @@ -524,6 +544,34 @@ namespace ICSharpCode.Decompiler.TypeSystem } #endregion + #region Decode Standalone Signature + public MethodSignature DecodeMethodSignature(StandaloneSignatureHandle handle, GenericContext genericContext) + { + var standaloneSignature = metadata.GetStandaloneSignature(handle); + if (standaloneSignature.GetKind() != StandaloneSignatureKind.Method) + throw new InvalidOperationException("Expected Method signature"); + var sig = standaloneSignature.DecodeMethodSignature(TypeProvider, genericContext); + return new MethodSignature( + sig.Header, + IntroduceTupleTypes(sig.ReturnType), + sig.RequiredParameterCount, + sig.GenericParameterCount, + ImmutableArray.CreateRange( + sig.ParameterTypes, IntroduceTupleTypes + ) + ); + } + + public ImmutableArray DecodeLocalSignature(StandaloneSignatureHandle handle, GenericContext genericContext) + { + var standaloneSignature = metadata.GetStandaloneSignature(handle); + if (standaloneSignature.GetKind() != StandaloneSignatureKind.LocalVariables) + throw new InvalidOperationException("Expected Local signature"); + var types = standaloneSignature.DecodeLocalSignature(TypeProvider, genericContext); + return ImmutableArray.CreateRange(types, IntroduceTupleTypes); + } + #endregion + #region Module / Assembly attributes /// /// Gets the list of all assembly attributes in the project. diff --git a/ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs deleted file mode 100644 index 39068f56b..000000000 --- a/ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright (c) 2014 Daniel Grunwald -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -using System; -using System.Collections.Immutable; -using System.Reflection.Metadata; -using ICSharpCode.Decompiler.Metadata; - -namespace ICSharpCode.Decompiler.TypeSystem -{ - /// - /// Decompiler type system for generic types or methods: - /// used to replace the dummy type parameters by the actual type parameters of the method being decompiled. - /// - public class SpecializingDecompilerTypeSystem : IDecompilerTypeSystem - { - readonly IDecompilerTypeSystem context; - readonly TypeParameterSubstitution substitution; - - public SpecializingDecompilerTypeSystem(IDecompilerTypeSystem context, TypeParameterSubstitution substitution) - { - if (context == null) - throw new ArgumentNullException(nameof(context)); - if (substitution == null) - throw new ArgumentNullException(nameof(substitution)); - this.context = context; - this.substitution = substitution; - } - - internal IDecompilerTypeSystem Context { - get { return context; } - } - - public ICompilation Compilation { - get { return context.Compilation; } - } - - public Metadata.PEFile ModuleDefinition => context.ModuleDefinition; - public MetadataModule MainModule => context.MainModule; - - public TypeParameterSubstitution Substitution { - get { return substitution; } - } - - public IType ResolveAsType(EntityHandle typeReference) - { - return context.ResolveAsType(typeReference).AcceptVisitor(substitution); - } - - public IField ResolveAsField(EntityHandle fieldReference) - { - IField field = context.ResolveAsField(fieldReference); - if (field != null) - field = (IField)field.Specialize(substitution); - return field; - } - - public IMethod ResolveAsMethod(EntityHandle methodReference) - { - IMethod method = context.ResolveAsMethod(methodReference); - if (method != null) - method = (IMethod)method.Specialize(substitution); - return method; - } - - public IDecompilerTypeSystem GetSpecializingTypeSystem(TypeParameterSubstitution newSubstitution) - { - //return context.GetSpecializingTypeSystem(TypeParameterSubstitution.Compose(newSubstitution, this.substitution)); - // Because the input new substitution is taken from IMember.Substitution for some member that - // was resolved by this type system, it already contains 'this.substitution'. - return context.GetSpecializingTypeSystem(newSubstitution); - } - - public MetadataReader GetMetadata() - { - return context.GetMetadata(); - } - - public IMember ResolveAsMember(EntityHandle memberReference) - { - IMember member = context.ResolveAsMember(memberReference); - if (member != null) - member = member.Specialize(substitution); - return member; - } - - MethodSignature IDecompilerTypeSystem.DecodeMethodSignature(StandaloneSignatureHandle standaloneSignatureHandle) - { - var sig = context.DecodeMethodSignature(standaloneSignatureHandle); - return new MethodSignature( - sig.Header, - sig.ReturnType.AcceptVisitor(substitution), - sig.RequiredParameterCount, - sig.GenericParameterCount, - ImmutableArray.CreateRange( - sig.ParameterTypes, t => t.AcceptVisitor(substitution) - ) - ); - } - - ImmutableArray IDecompilerTypeSystem.DecodeLocalSignature(StandaloneSignatureHandle standaloneSignatureHandle) - { - var sig = context.DecodeLocalSignature(standaloneSignatureHandle); - return ImmutableArray.CreateRange( - sig, t => t.AcceptVisitor(substitution) - ); - } - } -} diff --git a/ICSharpCode.Decompiler/TypeSystem/TypeParameterSubstitution.cs b/ICSharpCode.Decompiler/TypeSystem/TypeParameterSubstitution.cs index 8fc37bdd2..107fe0e9f 100644 --- a/ICSharpCode.Decompiler/TypeSystem/TypeParameterSubstitution.cs +++ b/ICSharpCode.Decompiler/TypeSystem/TypeParameterSubstitution.cs @@ -200,6 +200,10 @@ namespace ICSharpCode.Decompiler.TypeSystem b.Append(" -> "); b.Append(classTypeArguments[i].ReflectionName); } + if (classTypeArguments.Count == 0) { + if (first) first = false; else b.Append(", "); + b.Append("[]"); + } } if (methodTypeArguments != null) { for (int i = 0; i < methodTypeArguments.Count; i++) { @@ -209,6 +213,10 @@ namespace ICSharpCode.Decompiler.TypeSystem b.Append(" -> "); b.Append(methodTypeArguments[i].ReflectionName); } + if (methodTypeArguments.Count == 0) { + if (first) first = false; else b.Append(", "); + b.Append("[]"); + } } b.Append(']'); return b.ToString(); diff --git a/ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs b/ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs index 2dbd549f2..8377bfb88 100644 --- a/ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs +++ b/ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs @@ -54,11 +54,14 @@ namespace ILSpy.BamlDecompiler if (method == null || metadataEntry.RelativeVirtualAddress <= 0) return result; - + + var body = module.Reader.GetMethodBody(metadataEntry.RelativeVirtualAddress); + var genericContext = new ICSharpCode.Decompiler.TypeSystem.GenericContext( + classTypeParameters: method.DeclaringType?.TypeParameters, + methodTypeParameters: method.TypeParameters); // decompile method and optimize the switch - var ilReader = new ILReader(typeSystem); - var function = ilReader.ReadIL(module, (MethodDefinitionHandle)method.MetadataToken, - module.Reader.GetMethodBody(metadataEntry.RelativeVirtualAddress), cancellationToken); + var ilReader = new ILReader(typeSystem.MainModule); + var function = ilReader.ReadIL((MethodDefinitionHandle)method.MetadataToken, body, genericContext, cancellationToken); var context = new ILTransformContext(function, typeSystem, null) { CancellationToken = cancellationToken diff --git a/ILSpy/Languages/ILAstLanguage.cs b/ILSpy/Languages/ILAstLanguage.cs index 9b00afcd2..d3cd5a532 100644 --- a/ILSpy/Languages/ILAstLanguage.cs +++ b/ILSpy/Languages/ILAstLanguage.cs @@ -91,9 +91,9 @@ namespace ICSharpCode.ILSpy if (!methodDef.HasBody()) return; var typeSystem = new DecompilerTypeSystem(module, module.GetAssemblyResolver()); - ILReader reader = new ILReader(typeSystem); + ILReader reader = new ILReader(typeSystem.MainModule); var methodBody = module.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); - reader.WriteTypedIL(module, (SRM.MethodDefinitionHandle)method.MetadataToken, methodBody, output, options.CancellationToken); + reader.WriteTypedIL((SRM.MethodDefinitionHandle)method.MetadataToken, methodBody, output, cancellationToken: options.CancellationToken); } } @@ -116,11 +116,10 @@ namespace ICSharpCode.ILSpy return; IAssemblyResolver assemblyResolver = module.GetAssemblyResolver(); var typeSystem = new DecompilerTypeSystem(module, assemblyResolver); - var specializingTypeSystem = typeSystem.GetSpecializingTypeSystem(new SimpleTypeResolveContext(typeSystem.ResolveAsMethod(method.MetadataToken))); - var reader = new ILReader(specializingTypeSystem); + var reader = new ILReader(typeSystem.MainModule); reader.UseDebugSymbols = options.DecompilerSettings.UseDebugSymbols; var methodBody = module.Reader.GetMethodBody(methodDef.RelativeVirtualAddress); - ILFunction il = reader.ReadIL(module, (SRM.MethodDefinitionHandle)method.MetadataToken, methodBody, options.CancellationToken); + ILFunction il = reader.ReadIL((SRM.MethodDefinitionHandle)method.MetadataToken, methodBody, cancellationToken: options.CancellationToken); var namespaces = new HashSet(); var decompiler = new CSharpDecompiler(typeSystem, assemblyResolver, options.DecompilerSettings) { CancellationToken = options.CancellationToken }; ILTransformContext context = decompiler.CreateILTransformContext(il);