From b500b245483bc56f90df542845332b2daccd5511 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 18 Mar 2018 20:02:37 +0100 Subject: [PATCH] SRM WIP basic implementation of DecompilerTypeSystem --- .../CSharp/Resolver/CSharpOperators.cs | 2 +- .../Disassembler/DisassemblerHelpers.cs | 2 +- .../Disassembler/ILStructure.cs | 2 +- .../Disassembler/MethodBodyDisassembler.cs | 2 +- .../Disassembler/OpCodeInfo.cs | 16 +- .../Disassembler/ReflectionDisassembler.cs | 6 +- .../ICSharpCode.Decompiler.csproj | 6 +- ICSharpCode.Decompiler/IL/ILReader.cs | 821 +++++++++--------- .../IL/Instructions/CallIndirect.cs | 4 +- ICSharpCode.Decompiler/Metadata/Dom.cs | 40 +- .../Metadata/MetadataExtensions.cs | 35 +- .../Metadata/MetadataResolver.cs | 24 +- .../Metadata/UniversalAssemblyResolver.cs | 2 +- ICSharpCode.Decompiler/SRMExtensions.cs | 4 + ICSharpCode.Decompiler/SRMHacks.cs | 30 +- .../TypeSystem/DecompilerTypeSystem.cs | 360 ++++---- .../TypeSystem/IDecompilerTypeSystem.cs | 12 +- .../TypeSystem/MetadataLoader.cs | 640 ++++++-------- .../SpecializingDecompilerTypeSystem.cs | 12 +- .../Util/CollectionExtensions.cs | 13 +- ILSpy/SearchStrategies.cs | 4 +- 21 files changed, 1060 insertions(+), 977 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs b/ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs index ed485a4fa..ecc3d6f47 100644 --- a/ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs +++ b/ICSharpCode.Decompiler/CSharp/Resolver/CSharpOperators.cs @@ -116,7 +116,7 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver return null; } - public System.Reflection.Metadata.EntityHandle MetadataToken => default(System.Reflection.Metadata.EntityHandle); + public System.Reflection.Metadata.EntityHandle MetadataToken => default; ITypeDefinition IEntity.DeclaringTypeDefinition { get { return null; } diff --git a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs index 87f8cfdaf..f38939053 100644 --- a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs +++ b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs @@ -133,7 +133,7 @@ namespace ICSharpCode.Decompiler.Disassembler { var metadata = method.Module.GetMetadataReader(); var methodDefinition = metadata.GetMethodDefinition(method.Handle); - var signature = methodDefinition.DecodeSignature(new FullTypeNameSignatureDecoder(metadata), default(Unit)); + var signature = methodDefinition.DecodeSignature(new FullTypeNameSignatureDecoder(metadata), default); var parameters = methodDefinition.GetParameters().Select(p => metadata.GetParameter(p)).ToArray(); var signatureHeader = signature.Header; int index = sequence; diff --git a/ICSharpCode.Decompiler/Disassembler/ILStructure.cs b/ICSharpCode.Decompiler/Disassembler/ILStructure.cs index 21d0bdc36..3b69e3a98 100644 --- a/ICSharpCode.Decompiler/Disassembler/ILStructure.cs +++ b/ICSharpCode.Decompiler/Disassembler/ILStructure.cs @@ -132,7 +132,7 @@ namespace ICSharpCode.Decompiler.Disassembler SortChildren(); } - public ILStructure(Metadata.MethodDefinition method, ILStructureType type, int startOffset, int endOffset, ExceptionRegion handler = default(ExceptionRegion)) + public ILStructure(Metadata.MethodDefinition method, ILStructureType type, int startOffset, int endOffset, ExceptionRegion handler = default) { Debug.Assert(startOffset < endOffset); this.Method = method; diff --git a/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs index 0aea626ec..c1cca1a0a 100644 --- a/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs @@ -299,7 +299,7 @@ namespace ICSharpCode.Decompiler.Disassembler handle = MetadataTokens.EntityHandle(blob.ReadInt32()); switch (handle.Kind) { case HandleKind.MemberReference: - switch (method.Module.GetMetadataReader().GetMemberReference((MemberReferenceHandle)handle).GetKind()) { + switch (metadata.GetMemberReference((MemberReferenceHandle)handle).GetKind()) { case MemberReferenceKind.Method: output.Write("method "); break; diff --git a/ICSharpCode.Decompiler/Disassembler/OpCodeInfo.cs b/ICSharpCode.Decompiler/Disassembler/OpCodeInfo.cs index 44f226033..a380a4aaf 100644 --- a/ICSharpCode.Decompiler/Disassembler/OpCodeInfo.cs +++ b/ICSharpCode.Decompiler/Disassembler/OpCodeInfo.cs @@ -163,9 +163,21 @@ namespace ICSharpCode.Decompiler.Disassembler return targets; } - public static string DecodeUserString(ref BlobReader blob, Metadata.PEFile module) + public static string DecodeUserString(ref BlobReader blob, MetadataReader metadata) { - return module.GetMetadataReader().GetUserString(MetadataTokens.UserStringHandle(blob.ReadInt32())); + return metadata.GetUserString(MetadataTokens.UserStringHandle(blob.ReadInt32())); + } + + public static int DecodeIndex(ref BlobReader blob, ILOpCode opCode) + { + switch (opCode.GetOperandType()) { + case OperandType.ShortVariable: + return blob.ReadByte(); + case OperandType.Variable: + return blob.ReadUInt16(); + default: + throw new ArgumentException($"{opCode} not supported!"); + } } public static bool IsReturn(this ILOpCode opCode) diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs index ae7110c71..9f1a0fd48 100644 --- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs +++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs @@ -457,13 +457,13 @@ namespace ICSharpCode.Decompiler.Disassembler PrimitiveSerializationTypeCode ResolveEnumUnderlyingType(string typeName, PEFile module, out Metadata.TypeDefinition typeDefinition) { - typeDefinition = default(Metadata.TypeDefinition); + typeDefinition = default; TypeDefinitionHandle FindType(PEFile currentModule, string[] name) { var metadata = currentModule.GetMetadataReader(); var currentNamespace = metadata.GetNamespaceDefinitionRoot(); - ImmutableArray typeDefinitions = default(ImmutableArray); + ImmutableArray typeDefinitions = default; for (int i = 0; i < name.Length; i++) { string identifier = name[i]; @@ -489,7 +489,7 @@ namespace ICSharpCode.Decompiler.Disassembler } } } - return default(TypeDefinitionHandle); + return default; } string[] nameParts = typeName.Split(new[] { ", " }, 2, StringSplitOptions.None); string[] typeNameParts = nameParts[0].Split('.'); diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index 18267671c..8b9f72bbc 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -51,6 +51,10 @@ true + + 7.2 + + @@ -450,7 +454,7 @@ - + diff --git a/ICSharpCode.Decompiler/IL/ILReader.cs b/ICSharpCode.Decompiler/IL/ILReader.cs index 92c3c806f..4aac9ecb4 100644 --- a/ICSharpCode.Decompiler/IL/ILReader.cs +++ b/ICSharpCode.Decompiler/IL/ILReader.cs @@ -17,18 +17,19 @@ // DEALINGS IN THE SOFTWARE. using System; +using System.Collections; using System.Collections.Generic; -using System.Linq; using System.Collections.Immutable; using System.Diagnostics; -using Mono.Cecil; -using Cil = Mono.Cecil.Cil; -using System.Collections; +using System.Linq; using System.Threading; +using System.Reflection.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; using ArrayType = ICSharpCode.Decompiler.TypeSystem.ArrayType; using ByReferenceType = ICSharpCode.Decompiler.TypeSystem.ByReferenceType; +using ICSharpCode.Decompiler.Disassembler; +using System.Reflection.Metadata.Ecma335; namespace ICSharpCode.Decompiler.IL { @@ -48,11 +49,16 @@ namespace ICSharpCode.Decompiler.IL this.compilation = typeSystem.Compilation; } - Cil.MethodBody body; - Cil.MethodDebugInformation debugInfo; + MetadataReader metadata; + Metadata.MethodDefinition methodDefinition; + IMethod method; + MethodBodyBlock body; + Metadata.IDebugInfoProvider debugInfo; + ITypeResolveContext resolveContext; + MethodSignature methodSignature; StackType methodReturnStackType; - Cil.Instruction currentInstruction; - int nextInstructionIndex; + BlobReader reader; + int currentInstructionOffset; ImmutableStack currentStack; ILVariable[] parameterVariables; ILVariable[] localVariables; @@ -62,80 +68,100 @@ namespace ICSharpCode.Decompiler.IL // Dictionary that stores stacks for each IL instruction Dictionary> stackByOffset; - Dictionary variableByExceptionHandler; + Dictionary variableByExceptionHandler; UnionFind unionFind; List<(ILVariable, ILVariable)> stackMismatchPairs; IEnumerable stackVariables; - void Init(Cil.MethodBody body) + void Init(Metadata.MethodDefinition method, MethodBodyBlock body) { if (body == null) throw new ArgumentNullException(nameof(body)); + this.metadata = method.Module.GetMetadataReader(); + this.methodDefinition = method; + this.method = typeSystem.ResolveAsMethod(method.Handle); + this.methodSignature = metadata.GetMethodDefinition(method.Handle).DecodeSignature(new TypeSystem.Implementation.TypeReferenceSignatureDecoder(), default); this.body = body; - this.debugInfo = body.Method.DebugInformation; - this.currentInstruction = null; - this.nextInstructionIndex = 0; + this.reader = body.GetILReader(); + //this.debugInfo = metadata.GetMethodDebugInformation(method.Handle.ToDebugInformationHandle()); this.currentStack = ImmutableStack.Empty; this.unionFind = new UnionFind(); this.stackMismatchPairs = new List<(ILVariable, ILVariable)>(); - this.methodReturnStackType = typeSystem.Resolve(body.Method.ReturnType).GetStackType(); + this.resolveContext = new SimpleTypeResolveContext(this.method); + this.methodReturnStackType = methodSignature.ReturnType.Resolve(resolveContext).GetStackType(); InitParameterVariables(); - this.localVariables = body.Variables.SelectArray(CreateILVariable); - if (body.InitLocals) { + InitLocalVariables(); + if (body.LocalVariablesInitialized) { foreach (var v in localVariables) { v.HasInitialValue = true; } } this.mainContainer = new BlockContainer(expectedResultType: methodReturnStackType); this.instructionBuilder = new List(); - this.isBranchTarget = new BitArray(body.CodeSize); + this.isBranchTarget = new BitArray(reader.Length); this.stackByOffset = new Dictionary>(); - this.variableByExceptionHandler = new Dictionary(); + this.variableByExceptionHandler = new Dictionary(); } - IMetadataTokenProvider ReadAndDecodeMetadataToken() + EntityHandle ReadAndDecodeMetadataToken() { - return (IMetadataTokenProvider)currentInstruction.Operand; + return MetadataTokens.EntityHandle(reader.ReadInt32()); } IType ReadAndDecodeTypeReference() { - var typeReference = (TypeReference)currentInstruction.Operand; - return typeSystem.Resolve(typeReference); + var typeReference = MetadataTokens.EntityHandle(reader.ReadInt32()); + return typeSystem.ResolveAsType(typeReference); } IMethod ReadAndDecodeMethodReference() { - var methodReference = (MethodReference)currentInstruction.Operand; - return typeSystem.Resolve(methodReference); + var methodReference = MetadataTokens.EntityHandle(reader.ReadInt32()); + return typeSystem.ResolveAsMethod(methodReference); } IField ReadAndDecodeFieldReference() { - var fieldReference = (FieldReference)currentInstruction.Operand; - return typeSystem.Resolve(fieldReference); + var fieldReference = MetadataTokens.EntityHandle(reader.ReadInt32()); + return typeSystem.ResolveAsField(fieldReference); + } + + void InitLocalVariables() + { + if (body.LocalSignature.IsNil) return; + var standaloneSignature = metadata.GetStandaloneSignature(body.LocalSignature); + Debug.Assert(standaloneSignature.GetKind() == StandaloneSignatureKind.LocalVariables); + var variableTypes = standaloneSignature.DecodeLocalSignature(new TypeSystem.Implementation.TypeReferenceSignatureDecoder(), default); + localVariables = new ILVariable[variableTypes.Length]; + foreach (var (index, type) in variableTypes.WithIndex()) { + localVariables[index] = CreateILVariable(index, type); + } } void InitParameterVariables() { - parameterVariables = new ILVariable[GetPopCount(OpCode.Call, body.Method)]; - int paramIndex = 0; - if (body.Method.HasThis) - parameterVariables[paramIndex++] = CreateILVariable(body.ThisParameter); - foreach (var p in body.Method.Parameters) - parameterVariables[paramIndex++] = CreateILVariable(p); + parameterVariables = new ILVariable[GetPopCount(OpCode.Call, method)]; + int paramIndex = 0; int offset = 0; + if (methodSignature.Header.IsInstance) { + offset = 1; + parameterVariables[paramIndex++] = CreateILVariable(-1, method.DeclaringType.ToTypeReference(), "this"); + } + while (paramIndex < parameterVariables.Length) { + var type = methodSignature.ParameterTypes[paramIndex - offset]; + parameterVariables[paramIndex++] = CreateILVariable(paramIndex, type, method.Parameters[paramIndex - offset].Name); + } Debug.Assert(paramIndex == parameterVariables.Length); } - ILVariable CreateILVariable(Cil.VariableDefinition v) + ILVariable CreateILVariable(int index, ITypeReference type) { - VariableKind kind = IsPinned(v.VariableType) ? VariableKind.PinnedLocal : VariableKind.Local; - ILVariable ilVar = new ILVariable(kind, typeSystem.Resolve(v.VariableType), v.Index); - if (!UseDebugSymbols || debugInfo == null || !debugInfo.TryGetName(v, out string name)) { - ilVar.Name = "V_" + v.Index; + VariableKind kind = IsPinned(type) ? VariableKind.PinnedLocal : VariableKind.Local; + ILVariable ilVar = new ILVariable(kind, type.Resolve(resolveContext), index); + if (!UseDebugSymbols || debugInfo == null || !debugInfo.TryGetName(methodDefinition, index, out string name)) { + ilVar.Name = "V_" + index; ilVar.HasGeneratedName = true; } else if (string.IsNullOrWhiteSpace(name)) { - ilVar.Name = "V_" + v.Index; + ilVar.Name = "V_" + index; ilVar.HasGeneratedName = true; } else { ilVar.Name = name; @@ -143,46 +169,28 @@ namespace ICSharpCode.Decompiler.IL return ilVar; } - bool IsPinned(TypeReference type) + bool IsPinned(ITypeReference type) { - while (type is OptionalModifierType || type is RequiredModifierType) { - type = ((TypeSpecification)type).ElementType; - } - return type is PinnedType; + return type is TypeSystem.Implementation.PinnedTypeReference; } - ILVariable CreateILVariable(ParameterDefinition p) + ILVariable CreateILVariable(int index, ITypeReference typeReference, string name) { - IType parameterType; - if (p.Index == -1) { - // Manually construct ctor parameter type due to Cecil bug: - // https://github.com/jbevain/cecil/issues/275 - ITypeDefinition def = typeSystem.Resolve(body.Method.DeclaringType).GetDefinition(); - if (def != null && def.TypeParameterCount > 0) { - parameterType = new ParameterizedType(def, def.TypeArguments); - if (def.IsReferenceType == false) { - parameterType = new ByReferenceType(parameterType); - } - } else { - parameterType = typeSystem.Resolve(p.ParameterType); - } - } else { - parameterType = typeSystem.Resolve(p.ParameterType); - } + IType parameterType = typeReference.Resolve(resolveContext); Debug.Assert(!parameterType.IsUnbound()); if (parameterType.IsUnbound()) { // parameter types should not be unbound, the only known cause for these is a Cecil bug: - Debug.Assert(p.Index < 0); // cecil bug occurs only for "this" + Debug.Assert(index < 0); // cecil bug occurs only for "this" parameterType = new ParameterizedType(parameterType.GetDefinition(), parameterType.TypeArguments); } - var ilVar = new ILVariable(VariableKind.Parameter, parameterType, p.Index); + var ilVar = new ILVariable(VariableKind.Parameter, parameterType, index); Debug.Assert(ilVar.StoreCount == 1); // count the initial store when the method is called with an argument - if (p.Index < 0) + if (index < 0) ilVar.Name = "this"; - else if (string.IsNullOrEmpty(p.Name)) - ilVar.Name = "P_" + p.Index; + else if (string.IsNullOrEmpty(name)) + ilVar.Name = "P_" + index; else - ilVar.Name = p.Name; + ilVar.Name = name; return ilVar; } @@ -193,7 +201,7 @@ namespace ICSharpCode.Decompiler.IL /// void Warn(string message) { - Warnings.Add(string.Format("IL_{0:x4}: {1}", currentInstruction.Offset, message)); + Warnings.Add(string.Format("IL_{0:x4}: {1}", currentInstructionOffset, message)); } ImmutableStack MergeStacks(ImmutableStack a, ImmutableStack b) @@ -289,18 +297,18 @@ namespace ICSharpCode.Decompiler.IL void ReadInstructions(CancellationToken cancellationToken) { // Fill isBranchTarget and branchStackDict based on exception handlers - foreach (var eh in body.ExceptionHandlers) { + foreach (var eh in body.ExceptionRegions) { ImmutableStack ehStack = null; - if (eh.HandlerType == Cil.ExceptionHandlerType.Catch) { - var v = new ILVariable(VariableKind.Exception, typeSystem.Resolve(eh.CatchType), eh.HandlerStart.Offset) { - Name = "E_" + eh.HandlerStart.Offset, + if (eh.Kind == ExceptionRegionKind.Catch) { + var v = new ILVariable(VariableKind.Exception, typeSystem.ResolveAsType(eh.CatchType), eh.HandlerOffset) { + Name = "E_" + eh.HandlerOffset, HasGeneratedName = true }; variableByExceptionHandler.Add(eh, v); ehStack = ImmutableStack.Create(v); - } else if (eh.HandlerType == Cil.ExceptionHandlerType.Filter) { - var v = new ILVariable(VariableKind.Exception, typeSystem.Compilation.FindType(KnownTypeCode.Object), eh.HandlerStart.Offset) { - Name = "E_" + eh.HandlerStart.Offset, + } else if (eh.Kind == ExceptionRegionKind.Filter) { + var v = new ILVariable(VariableKind.Exception, typeSystem.Compilation.FindType(KnownTypeCode.Object), eh.HandlerOffset) { + Name = "E_" + eh.HandlerOffset, HasGeneratedName = true }; variableByExceptionHandler.Add(eh, v); @@ -308,25 +316,26 @@ namespace ICSharpCode.Decompiler.IL } else { ehStack = ImmutableStack.Empty; } - if (eh.FilterStart != null) { - isBranchTarget[eh.FilterStart.Offset] = true; - StoreStackForOffset(eh.FilterStart.Offset, ref ehStack); + if (eh.FilterOffset != -1) { + isBranchTarget[eh.FilterOffset] = true; + StoreStackForOffset(eh.FilterOffset, ref ehStack); } - if (eh.HandlerStart != null) { - isBranchTarget[eh.HandlerStart.Offset] = true; - StoreStackForOffset(eh.HandlerStart.Offset, ref ehStack); + if (eh.HandlerOffset != -1) { + isBranchTarget[eh.HandlerOffset] = true; + StoreStackForOffset(eh.HandlerOffset, ref ehStack); } } - - while (nextInstructionIndex < body.Instructions.Count) { + + reader.Reset(); + while (reader.RemainingBytes > 0) { cancellationToken.ThrowIfCancellationRequested(); - int start = body.Instructions[nextInstructionIndex].Offset; + int start = reader.Offset; StoreStackForOffset(start, ref currentStack); ILInstruction decodedInstruction = DecodeInstruction(); if (decodedInstruction.ResultType == StackType.Unknown) Warn("Unknown result type (might be due to invalid IL or missing references)"); decodedInstruction.CheckInvariant(ILPhase.InILReader); - int end = currentInstruction.GetEndOffset(); + int end = reader.Offset; decodedInstruction.ILRange = new Interval(start, end); UnpackPush(decodedInstruction).ILRange = decodedInstruction.ILRange; instructionBuilder.Add(decodedInstruction); @@ -335,7 +344,6 @@ namespace ICSharpCode.Decompiler.IL currentStack = ImmutableStack.Empty; } } - Debug.Assert(currentInstruction.Next == null || currentInstruction.Next.Offset == end); } var visitor = new CollectStackVariablesVisitor(unionFind); @@ -379,7 +387,7 @@ namespace ICSharpCode.Decompiler.IL /// /// Debugging helper: writes the decoded instruction stream interleaved with the inferred evaluation stack layout. /// - public void WriteTypedIL(Cil.MethodBody body, ITextOutput output, CancellationToken cancellationToken = default(CancellationToken)) + public void WriteTypedIL(Metadata.MethodDefinition method, MethodBodyBlock body, ITextOutput output, CancellationToken cancellationToken = default(CancellationToken)) { Init(body); ReadInstructions(cancellationToken); @@ -412,22 +420,22 @@ namespace ICSharpCode.Decompiler.IL inst.WriteTo(output, new ILAstWritingOptions()); output.WriteLine(); } - /*new Disassembler.MethodBodyDisassembler(output, cancellationToken) { DetectControlStructure = false } - .WriteExceptionHandlers(body);*/ + new Disassembler.MethodBodyDisassembler(output, cancellationToken) { DetectControlStructure = false } + .WriteExceptionHandlers(method, body); } /// /// Decodes the specified method body and returns an ILFunction. /// - public ILFunction ReadIL(Cil.MethodBody body, CancellationToken cancellationToken = default(CancellationToken)) + public ILFunction ReadIL(Metadata.MethodDefinition method, MethodBodyBlock body, CancellationToken cancellationToken = default(CancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); - Init(body); + Init(method, body); ReadInstructions(cancellationToken); var blockBuilder = new BlockBuilder(body, typeSystem, variableByExceptionHandler); blockBuilder.CreateBlocks(mainContainer, instructionBuilder, isBranchTarget, cancellationToken); - var method = typeSystem.Resolve(body.Method); - var function = new ILFunction(method, body.Method, mainContainer); + var resolvedMethod = typeSystem.Resolve(method); + var function = new ILFunction(resolvedMethod, method, mainContainer); CollectionExtensions.AddRange(function.Variables, parameterVariables); CollectionExtensions.AddRange(function.Variables, localVariables); CollectionExtensions.AddRange(function.Variables, stackVariables); @@ -471,469 +479,468 @@ namespace ICSharpCode.Decompiler.IL ILInstruction DecodeInstruction() { - if (nextInstructionIndex >= body.Instructions.Count) + if (reader.RemainingBytes == 0) return new InvalidBranch("Unexpected end of body"); - var cecilInst = body.Instructions[nextInstructionIndex++]; - currentInstruction = cecilInst; - switch (cecilInst.OpCode.Code) { - case Cil.Code.Constrained: + var opCode = ILParser.DecodeOpCode(ref reader); + switch (opCode) { + case ILOpCode.Constrained: return DecodeConstrainedCall(); - case Cil.Code.Readonly: + case ILOpCode.Readonly: return DecodeReadonly(); - case Cil.Code.Tail: + case ILOpCode.Tail: return DecodeTailCall(); - case Cil.Code.Unaligned: + case ILOpCode.Unaligned: return DecodeUnaligned(); - case Cil.Code.Volatile: + case ILOpCode.Volatile: return DecodeVolatile(); - case Cil.Code.Add: + case ILOpCode.Add: return BinaryNumeric(BinaryNumericOperator.Add); - case Cil.Code.Add_Ovf: + case ILOpCode.Add_ovf: return BinaryNumeric(BinaryNumericOperator.Add, true, Sign.Signed); - case Cil.Code.Add_Ovf_Un: + case ILOpCode.Add_ovf_un: return BinaryNumeric(BinaryNumericOperator.Add, true, Sign.Unsigned); - case Cil.Code.And: + case ILOpCode.And: return BinaryNumeric(BinaryNumericOperator.BitAnd); - case Cil.Code.Arglist: + case ILOpCode.Arglist: return Push(new Arglist()); - case Cil.Code.Beq: - return DecodeComparisonBranch(false, ComparisonKind.Equality); - case Cil.Code.Beq_S: - return DecodeComparisonBranch(true, ComparisonKind.Equality); - case Cil.Code.Bge: - return DecodeComparisonBranch(false, ComparisonKind.GreaterThanOrEqual); - case Cil.Code.Bge_S: - return DecodeComparisonBranch(true, ComparisonKind.GreaterThanOrEqual); - case Cil.Code.Bge_Un: - return DecodeComparisonBranch(false, ComparisonKind.GreaterThanOrEqual, un: true); - case Cil.Code.Bge_Un_S: - return DecodeComparisonBranch(true, ComparisonKind.GreaterThanOrEqual, un: true); - case Cil.Code.Bgt: - return DecodeComparisonBranch(false, ComparisonKind.GreaterThan); - case Cil.Code.Bgt_S: - return DecodeComparisonBranch(true, ComparisonKind.GreaterThan); - case Cil.Code.Bgt_Un: - return DecodeComparisonBranch(false, ComparisonKind.GreaterThan, un: true); - case Cil.Code.Bgt_Un_S: - return DecodeComparisonBranch(true, ComparisonKind.GreaterThan, un: true); - case Cil.Code.Ble: - return DecodeComparisonBranch(false, ComparisonKind.LessThanOrEqual); - case Cil.Code.Ble_S: - return DecodeComparisonBranch(true, ComparisonKind.LessThanOrEqual); - case Cil.Code.Ble_Un: - return DecodeComparisonBranch(false, ComparisonKind.LessThanOrEqual, un: true); - case Cil.Code.Ble_Un_S: - return DecodeComparisonBranch(true, ComparisonKind.LessThanOrEqual, un: true); - case Cil.Code.Blt: - return DecodeComparisonBranch(false, ComparisonKind.LessThan); - case Cil.Code.Blt_S: - return DecodeComparisonBranch(true, ComparisonKind.LessThan); - case Cil.Code.Blt_Un: - return DecodeComparisonBranch(false, ComparisonKind.LessThan, un: true); - case Cil.Code.Blt_Un_S: - return DecodeComparisonBranch(true, ComparisonKind.LessThan, un: true); - case Cil.Code.Bne_Un: - return DecodeComparisonBranch(false, ComparisonKind.Inequality, un: true); - case Cil.Code.Bne_Un_S: - return DecodeComparisonBranch(true, ComparisonKind.Inequality, un: true); - case Cil.Code.Br: - return DecodeUnconditionalBranch(false); - case Cil.Code.Br_S: - return DecodeUnconditionalBranch(true); - case Cil.Code.Break: + case ILOpCode.Beq: + return DecodeComparisonBranch(opCode, ComparisonKind.Equality); + case ILOpCode.Beq_s: + return DecodeComparisonBranch(opCode, ComparisonKind.Equality); + case ILOpCode.Bge: + return DecodeComparisonBranch(opCode, ComparisonKind.GreaterThanOrEqual); + case ILOpCode.Bge_s: + return DecodeComparisonBranch(opCode, ComparisonKind.GreaterThanOrEqual); + case ILOpCode.Bge_un: + return DecodeComparisonBranch(opCode, ComparisonKind.GreaterThanOrEqual, un: true); + case ILOpCode.Bge_un_s: + return DecodeComparisonBranch(opCode, ComparisonKind.GreaterThanOrEqual, un: true); + case ILOpCode.Bgt: + return DecodeComparisonBranch(opCode, ComparisonKind.GreaterThan); + case ILOpCode.Bgt_s: + return DecodeComparisonBranch(opCode, ComparisonKind.GreaterThan); + case ILOpCode.Bgt_un: + return DecodeComparisonBranch(opCode, ComparisonKind.GreaterThan, un: true); + case ILOpCode.Bgt_un_s: + return DecodeComparisonBranch(opCode, ComparisonKind.GreaterThan, un: true); + case ILOpCode.Ble: + return DecodeComparisonBranch(opCode, ComparisonKind.LessThanOrEqual); + case ILOpCode.Ble_s: + return DecodeComparisonBranch(opCode, ComparisonKind.LessThanOrEqual); + case ILOpCode.Ble_un: + return DecodeComparisonBranch(opCode, ComparisonKind.LessThanOrEqual, un: true); + case ILOpCode.Ble_un_s: + return DecodeComparisonBranch(opCode, ComparisonKind.LessThanOrEqual, un: true); + case ILOpCode.Blt: + return DecodeComparisonBranch(opCode, ComparisonKind.LessThan); + case ILOpCode.Blt_s: + return DecodeComparisonBranch(opCode, ComparisonKind.LessThan); + case ILOpCode.Blt_un: + return DecodeComparisonBranch(opCode, ComparisonKind.LessThan, un: true); + case ILOpCode.Blt_un_s: + return DecodeComparisonBranch(opCode, ComparisonKind.LessThan, un: true); + case ILOpCode.Bne_un: + return DecodeComparisonBranch(opCode, ComparisonKind.Inequality, un: true); + case ILOpCode.Bne_un_s: + return DecodeComparisonBranch(opCode, ComparisonKind.Inequality, un: true); + case ILOpCode.Br: + return DecodeUnconditionalBranch(opCode); + case ILOpCode.Br_s: + return DecodeUnconditionalBranch(opCode); + case ILOpCode.Break: return new DebugBreak(); - case Cil.Code.Brfalse: - return DecodeConditionalBranch(false, true); - case Cil.Code.Brfalse_S: - return DecodeConditionalBranch(true, true); - case Cil.Code.Brtrue: - return DecodeConditionalBranch(false, false); - case Cil.Code.Brtrue_S: - return DecodeConditionalBranch(true, false); - case Cil.Code.Call: + case ILOpCode.Brfalse: + return DecodeConditionalBranch(opCode, true); + case ILOpCode.Brfalse_s: + return DecodeConditionalBranch(opCode, true); + case ILOpCode.Brtrue: + return DecodeConditionalBranch(opCode, false); + case ILOpCode.Brtrue_s: + return DecodeConditionalBranch(opCode, false); + case ILOpCode.Call: return DecodeCall(OpCode.Call); - case Cil.Code.Callvirt: + case ILOpCode.Callvirt: return DecodeCall(OpCode.CallVirt); - case Cil.Code.Calli: + case ILOpCode.Calli: return DecodeCallIndirect(); - case Cil.Code.Ceq: + case ILOpCode.Ceq: return Push(Comparison(ComparisonKind.Equality)); - case Cil.Code.Cgt: + case ILOpCode.Cgt: return Push(Comparison(ComparisonKind.GreaterThan)); - case Cil.Code.Cgt_Un: + case ILOpCode.Cgt_un: return Push(Comparison(ComparisonKind.GreaterThan, un: true)); - case Cil.Code.Clt: + case ILOpCode.Clt: return Push(Comparison(ComparisonKind.LessThan)); - case Cil.Code.Clt_Un: + case ILOpCode.Clt_un: return Push(Comparison(ComparisonKind.LessThan, un: true)); - case Cil.Code.Ckfinite: + case ILOpCode.Ckfinite: return new Ckfinite(Peek()); - case Cil.Code.Conv_I1: + case ILOpCode.Conv_i1: return Push(new Conv(Pop(), PrimitiveType.I1, false, Sign.None)); - case Cil.Code.Conv_I2: + case ILOpCode.Conv_i2: return Push(new Conv(Pop(), PrimitiveType.I2, false, Sign.None)); - case Cil.Code.Conv_I4: + case ILOpCode.Conv_i4: return Push(new Conv(Pop(), PrimitiveType.I4, false, Sign.None)); - case Cil.Code.Conv_I8: + case ILOpCode.Conv_i8: return Push(new Conv(Pop(), PrimitiveType.I8, false, Sign.None)); - case Cil.Code.Conv_R4: + case ILOpCode.Conv_r4: return Push(new Conv(Pop(), PrimitiveType.R4, false, Sign.Signed)); - case Cil.Code.Conv_R8: + case ILOpCode.Conv_r8: return Push(new Conv(Pop(), PrimitiveType.R8, false, Sign.Signed)); - case Cil.Code.Conv_U1: + case ILOpCode.Conv_u1: return Push(new Conv(Pop(), PrimitiveType.U1, false, Sign.None)); - case Cil.Code.Conv_U2: + case ILOpCode.Conv_u2: return Push(new Conv(Pop(), PrimitiveType.U2, false, Sign.None)); - case Cil.Code.Conv_U4: + case ILOpCode.Conv_u4: return Push(new Conv(Pop(), PrimitiveType.U4, false, Sign.None)); - case Cil.Code.Conv_U8: + case ILOpCode.Conv_u8: return Push(new Conv(Pop(), PrimitiveType.U8, false, Sign.None)); - case Cil.Code.Conv_I: + case ILOpCode.Conv_i: return Push(new Conv(Pop(), PrimitiveType.I, false, Sign.None)); - case Cil.Code.Conv_U: + case ILOpCode.Conv_u: return Push(new Conv(Pop(), PrimitiveType.U, false, Sign.None)); - case Cil.Code.Conv_R_Un: + case ILOpCode.Conv_r_un: return Push(new Conv(Pop(), PrimitiveType.R8, false, Sign.Unsigned)); - case Cil.Code.Conv_Ovf_I1: + case ILOpCode.Conv_ovf_i1: return Push(new Conv(Pop(), PrimitiveType.I1, true, Sign.Signed)); - case Cil.Code.Conv_Ovf_I2: + case ILOpCode.Conv_ovf_i2: return Push(new Conv(Pop(), PrimitiveType.I2, true, Sign.Signed)); - case Cil.Code.Conv_Ovf_I4: + case ILOpCode.Conv_ovf_i4: return Push(new Conv(Pop(), PrimitiveType.I4, true, Sign.Signed)); - case Cil.Code.Conv_Ovf_I8: + case ILOpCode.Conv_ovf_i8: return Push(new Conv(Pop(), PrimitiveType.I8, true, Sign.Signed)); - case Cil.Code.Conv_Ovf_U1: + case ILOpCode.Conv_ovf_u1: return Push(new Conv(Pop(), PrimitiveType.U1, true, Sign.Signed)); - case Cil.Code.Conv_Ovf_U2: + case ILOpCode.Conv_ovf_u2: return Push(new Conv(Pop(), PrimitiveType.U2, true, Sign.Signed)); - case Cil.Code.Conv_Ovf_U4: + case ILOpCode.Conv_ovf_u4: return Push(new Conv(Pop(), PrimitiveType.U4, true, Sign.Signed)); - case Cil.Code.Conv_Ovf_U8: + case ILOpCode.Conv_ovf_u8: return Push(new Conv(Pop(), PrimitiveType.U8, true, Sign.Signed)); - case Cil.Code.Conv_Ovf_I: + case ILOpCode.Conv_ovf_i: return Push(new Conv(Pop(), PrimitiveType.I, true, Sign.Signed)); - case Cil.Code.Conv_Ovf_U: + case ILOpCode.Conv_ovf_u: return Push(new Conv(Pop(), PrimitiveType.U, true, Sign.Signed)); - case Cil.Code.Conv_Ovf_I1_Un: + case ILOpCode.Conv_ovf_i1_un: return Push(new Conv(Pop(), PrimitiveType.I1, true, Sign.Unsigned)); - case Cil.Code.Conv_Ovf_I2_Un: + case ILOpCode.Conv_ovf_i2_un: return Push(new Conv(Pop(), PrimitiveType.I2, true, Sign.Unsigned)); - case Cil.Code.Conv_Ovf_I4_Un: + case ILOpCode.Conv_ovf_i4_un: return Push(new Conv(Pop(), PrimitiveType.I4, true, Sign.Unsigned)); - case Cil.Code.Conv_Ovf_I8_Un: + case ILOpCode.Conv_ovf_i8_un: return Push(new Conv(Pop(), PrimitiveType.I8, true, Sign.Unsigned)); - case Cil.Code.Conv_Ovf_U1_Un: + case ILOpCode.Conv_ovf_u1_un: return Push(new Conv(Pop(), PrimitiveType.U1, true, Sign.Unsigned)); - case Cil.Code.Conv_Ovf_U2_Un: + case ILOpCode.Conv_ovf_u2_un: return Push(new Conv(Pop(), PrimitiveType.U2, true, Sign.Unsigned)); - case Cil.Code.Conv_Ovf_U4_Un: + case ILOpCode.Conv_ovf_u4_un: return Push(new Conv(Pop(), PrimitiveType.U4, true, Sign.Unsigned)); - case Cil.Code.Conv_Ovf_U8_Un: + case ILOpCode.Conv_ovf_u8_un: return Push(new Conv(Pop(), PrimitiveType.U8, true, Sign.Unsigned)); - case Cil.Code.Conv_Ovf_I_Un: + case ILOpCode.Conv_ovf_i_un: return Push(new Conv(Pop(), PrimitiveType.I, true, Sign.Unsigned)); - case Cil.Code.Conv_Ovf_U_Un: + case ILOpCode.Conv_ovf_u_un: return Push(new Conv(Pop(), PrimitiveType.U, true, Sign.Unsigned)); - case Cil.Code.Cpblk: + case ILOpCode.Cpblk: return new Cpblk(size: Pop(StackType.I4), sourceAddress: PopPointer(), destAddress: PopPointer()); - case Cil.Code.Div: + case ILOpCode.Div: return BinaryNumeric(BinaryNumericOperator.Div, false, Sign.Signed); - case Cil.Code.Div_Un: + case ILOpCode.Div_un: return BinaryNumeric(BinaryNumericOperator.Div, false, Sign.Unsigned); - case Cil.Code.Dup: + case ILOpCode.Dup: return Push(Peek()); - case Cil.Code.Endfilter: + case ILOpCode.Endfilter: return new Leave(null, Pop()); - case Cil.Code.Endfinally: + case ILOpCode.Endfinally: return new Leave(null); - case Cil.Code.Initblk: + case ILOpCode.Initblk: return new Initblk(size: Pop(StackType.I4), value: Pop(StackType.I4), address: PopPointer()); - case Cil.Code.Jmp: + case ILOpCode.Jmp: return DecodeJmp(); - case Cil.Code.Ldarg: - case Cil.Code.Ldarg_S: - return Push(Ldarg(((ParameterDefinition)cecilInst.Operand).Sequence)); - case Cil.Code.Ldarg_0: + case ILOpCode.Ldarg: + case ILOpCode.Ldarg_s: + return Push(Ldarg(ILParser.DecodeIndex(ref reader, opCode))); + case ILOpCode.Ldarg_0: return Push(Ldarg(0)); - case Cil.Code.Ldarg_1: + case ILOpCode.Ldarg_1: return Push(Ldarg(1)); - case Cil.Code.Ldarg_2: + case ILOpCode.Ldarg_2: return Push(Ldarg(2)); - case Cil.Code.Ldarg_3: + case ILOpCode.Ldarg_3: return Push(Ldarg(3)); - case Cil.Code.Ldarga: - case Cil.Code.Ldarga_S: - return Push(Ldarga(((ParameterDefinition)cecilInst.Operand).Sequence)); - case Cil.Code.Ldc_I4: - return Push(new LdcI4((int)cecilInst.Operand)); - case Cil.Code.Ldc_I8: - return Push(new LdcI8((long)cecilInst.Operand)); - case Cil.Code.Ldc_R4: - return Push(new LdcF4((float)cecilInst.Operand)); - case Cil.Code.Ldc_R8: - return Push(new LdcF8((double)cecilInst.Operand)); - case Cil.Code.Ldc_I4_M1: + case ILOpCode.Ldarga: + case ILOpCode.Ldarga_s: + return Push(Ldarga(ILParser.DecodeIndex(ref reader, opCode))); + case ILOpCode.Ldc_i4: + return Push(new LdcI4(reader.ReadInt32())); + case ILOpCode.Ldc_i8: + return Push(new LdcI8(reader.ReadInt64())); + case ILOpCode.Ldc_r4: + return Push(new LdcF4(reader.ReadSingle())); + case ILOpCode.Ldc_r8: + return Push(new LdcF8(reader.ReadDouble())); + case ILOpCode.Ldc_i4_m1: return Push(new LdcI4(-1)); - case Cil.Code.Ldc_I4_0: + case ILOpCode.Ldc_i4_0: return Push(new LdcI4(0)); - case Cil.Code.Ldc_I4_1: + case ILOpCode.Ldc_i4_1: return Push(new LdcI4(1)); - case Cil.Code.Ldc_I4_2: + case ILOpCode.Ldc_i4_2: return Push(new LdcI4(2)); - case Cil.Code.Ldc_I4_3: + case ILOpCode.Ldc_i4_3: return Push(new LdcI4(3)); - case Cil.Code.Ldc_I4_4: + case ILOpCode.Ldc_i4_4: return Push(new LdcI4(4)); - case Cil.Code.Ldc_I4_5: + case ILOpCode.Ldc_i4_5: return Push(new LdcI4(5)); - case Cil.Code.Ldc_I4_6: + case ILOpCode.Ldc_i4_6: return Push(new LdcI4(6)); - case Cil.Code.Ldc_I4_7: + case ILOpCode.Ldc_i4_7: return Push(new LdcI4(7)); - case Cil.Code.Ldc_I4_8: + case ILOpCode.Ldc_i4_8: return Push(new LdcI4(8)); - case Cil.Code.Ldc_I4_S: - return Push(new LdcI4((sbyte)cecilInst.Operand)); - case Cil.Code.Ldnull: + case ILOpCode.Ldc_i4_s: + return Push(new LdcI4(reader.ReadSByte())); + case ILOpCode.Ldnull: return Push(new LdNull()); - case Cil.Code.Ldstr: + case ILOpCode.Ldstr: return Push(DecodeLdstr()); - case Cil.Code.Ldftn: + case ILOpCode.Ldftn: return Push(new LdFtn(ReadAndDecodeMethodReference())); - case Cil.Code.Ldind_I1: + case ILOpCode.Ldind_i1: return Push(new LdObj(PopPointer(), compilation.FindType(KnownTypeCode.SByte))); - case Cil.Code.Ldind_I2: + case ILOpCode.Ldind_i2: return Push(new LdObj(PopPointer(), compilation.FindType(KnownTypeCode.Int16))); - case Cil.Code.Ldind_I4: + case ILOpCode.Ldind_i4: return Push(new LdObj(PopPointer(), compilation.FindType(KnownTypeCode.Int32))); - case Cil.Code.Ldind_I8: + case ILOpCode.Ldind_i8: return Push(new LdObj(PopPointer(), compilation.FindType(KnownTypeCode.Int64))); - case Cil.Code.Ldind_U1: + case ILOpCode.Ldind_u1: return Push(new LdObj(PopPointer(), compilation.FindType(KnownTypeCode.Byte))); - case Cil.Code.Ldind_U2: + case ILOpCode.Ldind_u2: return Push(new LdObj(PopPointer(), compilation.FindType(KnownTypeCode.UInt16))); - case Cil.Code.Ldind_U4: + case ILOpCode.Ldind_u4: return Push(new LdObj(PopPointer(), compilation.FindType(KnownTypeCode.UInt32))); - case Cil.Code.Ldind_R4: + case ILOpCode.Ldind_r4: return Push(new LdObj(PopPointer(), compilation.FindType(KnownTypeCode.Single))); - case Cil.Code.Ldind_R8: + case ILOpCode.Ldind_r8: return Push(new LdObj(PopPointer(), compilation.FindType(KnownTypeCode.Double))); - case Cil.Code.Ldind_I: + case ILOpCode.Ldind_i: return Push(new LdObj(PopPointer(), compilation.FindType(KnownTypeCode.IntPtr))); - case Cil.Code.Ldind_Ref: + case ILOpCode.Ldind_ref: return Push(new LdObj(PopPointer(), compilation.FindType(KnownTypeCode.Object))); - case Cil.Code.Ldloc: - case Cil.Code.Ldloc_S: - return Push(Ldloc(((Cil.VariableDefinition)cecilInst.Operand).Index)); - case Cil.Code.Ldloc_0: + case ILOpCode.Ldloc: + case ILOpCode.Ldloc_s: + return Push(Ldloc(ILParser.DecodeIndex(ref reader, opCode))); + case ILOpCode.Ldloc_0: return Push(Ldloc(0)); - case Cil.Code.Ldloc_1: + case ILOpCode.Ldloc_1: return Push(Ldloc(1)); - case Cil.Code.Ldloc_2: + case ILOpCode.Ldloc_2: return Push(Ldloc(2)); - case Cil.Code.Ldloc_3: + case ILOpCode.Ldloc_3: return Push(Ldloc(3)); - case Cil.Code.Ldloca: - case Cil.Code.Ldloca_S: - return Push(Ldloca(((Cil.VariableDefinition)cecilInst.Operand).Index)); - case Cil.Code.Leave: - return DecodeUnconditionalBranch(false, isLeave: true); - case Cil.Code.Leave_S: - return DecodeUnconditionalBranch(true, isLeave: true); - case Cil.Code.Localloc: + case ILOpCode.Ldloca: + case ILOpCode.Ldloca_s: + return Push(Ldloca(ILParser.DecodeIndex(ref reader, opCode))); + case ILOpCode.Leave: + return DecodeUnconditionalBranch(opCode, isLeave: true); + case ILOpCode.Leave_s: + return DecodeUnconditionalBranch(opCode, isLeave: true); + case ILOpCode.Localloc: return Push(new LocAlloc(Pop())); - case Cil.Code.Mul: + case ILOpCode.Mul: return BinaryNumeric(BinaryNumericOperator.Mul, false, Sign.None); - case Cil.Code.Mul_Ovf: + case ILOpCode.Mul_ovf: return BinaryNumeric(BinaryNumericOperator.Mul, true, Sign.Signed); - case Cil.Code.Mul_Ovf_Un: + case ILOpCode.Mul_ovf_un: return BinaryNumeric(BinaryNumericOperator.Mul, true, Sign.Unsigned); - case Cil.Code.Neg: + case ILOpCode.Neg: return Neg(); - case Cil.Code.Newobj: + case ILOpCode.Newobj: return DecodeCall(OpCode.NewObj); - case Cil.Code.Nop: + case ILOpCode.Nop: return new Nop(); - case Cil.Code.Not: + case ILOpCode.Not: return Push(new BitNot(Pop())); - case Cil.Code.Or: + case ILOpCode.Or: return BinaryNumeric(BinaryNumericOperator.BitOr); - case Cil.Code.Pop: + case ILOpCode.Pop: Pop(); return new Nop() { Kind = NopKind.Pop }; - case Cil.Code.Rem: + case ILOpCode.Rem: return BinaryNumeric(BinaryNumericOperator.Rem, false, Sign.Signed); - case Cil.Code.Rem_Un: + case ILOpCode.Rem_un: return BinaryNumeric(BinaryNumericOperator.Rem, false, Sign.Unsigned); - case Cil.Code.Ret: + case ILOpCode.Ret: return Return(); - case Cil.Code.Shl: + case ILOpCode.Shl: return BinaryNumeric(BinaryNumericOperator.ShiftLeft, false, Sign.None); - case Cil.Code.Shr: + case ILOpCode.Shr: return BinaryNumeric(BinaryNumericOperator.ShiftRight, false, Sign.Signed); - case Cil.Code.Shr_Un: + case ILOpCode.Shr_un: return BinaryNumeric(BinaryNumericOperator.ShiftRight, false, Sign.Unsigned); - case Cil.Code.Starg: - case Cil.Code.Starg_S: - return Starg(((ParameterDefinition)cecilInst.Operand).Sequence); - case Cil.Code.Stind_I1: + case ILOpCode.Starg: + case ILOpCode.Starg_s: + return Starg(ILParser.DecodeIndex(ref reader, opCode)); + case ILOpCode.Stind_i1: return new StObj(value: Pop(StackType.I4), target: PopPointer(), type: compilation.FindType(KnownTypeCode.SByte)); - case Cil.Code.Stind_I2: + case ILOpCode.Stind_i2: return new StObj(value: Pop(StackType.I4), target: PopPointer(), type: compilation.FindType(KnownTypeCode.Int16)); - case Cil.Code.Stind_I4: + case ILOpCode.Stind_i4: return new StObj(value: Pop(StackType.I4), target: PopPointer(), type: compilation.FindType(KnownTypeCode.Int32)); - case Cil.Code.Stind_I8: + case ILOpCode.Stind_i8: return new StObj(value: Pop(StackType.I8), target: PopPointer(), type: compilation.FindType(KnownTypeCode.Int64)); - case Cil.Code.Stind_R4: + case ILOpCode.Stind_r4: return new StObj(value: Pop(StackType.F4), target: PopPointer(), type: compilation.FindType(KnownTypeCode.Single)); - case Cil.Code.Stind_R8: + case ILOpCode.Stind_r8: return new StObj(value: Pop(StackType.F8), target: PopPointer(), type: compilation.FindType(KnownTypeCode.Double)); - case Cil.Code.Stind_I: + case ILOpCode.Stind_i: return new StObj(value: Pop(StackType.I), target: PopPointer(), type: compilation.FindType(KnownTypeCode.IntPtr)); - case Cil.Code.Stind_Ref: + case ILOpCode.Stind_ref: return new StObj(value: Pop(StackType.O), target: PopPointer(), type: compilation.FindType(KnownTypeCode.Object)); - case Cil.Code.Stloc: - case Cil.Code.Stloc_S: - return Stloc(((Cil.VariableDefinition)cecilInst.Operand).Index); - case Cil.Code.Stloc_0: + case ILOpCode.Stloc: + case ILOpCode.Stloc_s: + return Stloc(ILParser.DecodeIndex(ref reader, opCode)); + case ILOpCode.Stloc_0: return Stloc(0); - case Cil.Code.Stloc_1: + case ILOpCode.Stloc_1: return Stloc(1); - case Cil.Code.Stloc_2: + case ILOpCode.Stloc_2: return Stloc(2); - case Cil.Code.Stloc_3: + case ILOpCode.Stloc_3: return Stloc(3); - case Cil.Code.Sub: + case ILOpCode.Sub: return BinaryNumeric(BinaryNumericOperator.Sub, false, Sign.None); - case Cil.Code.Sub_Ovf: + case ILOpCode.Sub_ovf: return BinaryNumeric(BinaryNumericOperator.Sub, true, Sign.Signed); - case Cil.Code.Sub_Ovf_Un: + case ILOpCode.Sub_ovf_un: return BinaryNumeric(BinaryNumericOperator.Sub, true, Sign.Unsigned); - case Cil.Code.Switch: + case ILOpCode.Switch: return DecodeSwitch(); - case Cil.Code.Xor: + case ILOpCode.Xor: return BinaryNumeric(BinaryNumericOperator.BitXor); - case Cil.Code.Box: + case ILOpCode.Box: { var type = ReadAndDecodeTypeReference(); return Push(new Box(Pop(type.GetStackType()), type)); } - case Cil.Code.Castclass: + case ILOpCode.Castclass: return Push(new CastClass(Pop(StackType.O), ReadAndDecodeTypeReference())); - case Cil.Code.Cpobj: + case ILOpCode.Cpobj: { var type = ReadAndDecodeTypeReference(); var ld = new LdObj(PopPointer(), type); return new StObj(PopPointer(), ld, type); } - case Cil.Code.Initobj: + case ILOpCode.Initobj: return InitObj(PopPointer(), ReadAndDecodeTypeReference()); - case Cil.Code.Isinst: + case ILOpCode.Isinst: return Push(new IsInst(Pop(StackType.O), ReadAndDecodeTypeReference())); - case Cil.Code.Ldelem_Any: + case ILOpCode.Ldelem: return LdElem(ReadAndDecodeTypeReference()); - case Cil.Code.Ldelem_I1: + case ILOpCode.Ldelem_i1: return LdElem(compilation.FindType(KnownTypeCode.SByte)); - case Cil.Code.Ldelem_I2: + case ILOpCode.Ldelem_i2: return LdElem(compilation.FindType(KnownTypeCode.Int16)); - case Cil.Code.Ldelem_I4: + case ILOpCode.Ldelem_i4: return LdElem(compilation.FindType(KnownTypeCode.Int32)); - case Cil.Code.Ldelem_I8: + case ILOpCode.Ldelem_i8: return LdElem(compilation.FindType(KnownTypeCode.Int64)); - case Cil.Code.Ldelem_U1: + case ILOpCode.Ldelem_u1: return LdElem(compilation.FindType(KnownTypeCode.Byte)); - case Cil.Code.Ldelem_U2: + case ILOpCode.Ldelem_u2: return LdElem(compilation.FindType(KnownTypeCode.UInt16)); - case Cil.Code.Ldelem_U4: + case ILOpCode.Ldelem_u4: return LdElem(compilation.FindType(KnownTypeCode.UInt32)); - case Cil.Code.Ldelem_R4: + case ILOpCode.Ldelem_r4: return LdElem(compilation.FindType(KnownTypeCode.Single)); - case Cil.Code.Ldelem_R8: + case ILOpCode.Ldelem_r8: return LdElem(compilation.FindType(KnownTypeCode.Double)); - case Cil.Code.Ldelem_I: + case ILOpCode.Ldelem_i: return LdElem(compilation.FindType(KnownTypeCode.IntPtr)); - case Cil.Code.Ldelem_Ref: + case ILOpCode.Ldelem_ref: return LdElem(compilation.FindType(KnownTypeCode.Object)); - case Cil.Code.Ldelema: + case ILOpCode.Ldelema: return Push(new LdElema(indices: Pop(), array: Pop(), type: ReadAndDecodeTypeReference())); - case Cil.Code.Ldfld: + case ILOpCode.Ldfld: { var field = ReadAndDecodeFieldReference(); return Push(new LdObj(new LdFlda(PopLdFldTarget(field), field) { DelayExceptions = true }, field.Type)); } - case Cil.Code.Ldflda: + case ILOpCode.Ldflda: { var field = ReadAndDecodeFieldReference(); return Push(new LdFlda(PopFieldTarget(field), field)); } - case Cil.Code.Stfld: + case ILOpCode.Stfld: { var field = ReadAndDecodeFieldReference(); return new StObj(value: Pop(field.Type.GetStackType()), target: new LdFlda(PopFieldTarget(field), field) { DelayExceptions = true }, type: field.Type); } - case Cil.Code.Ldlen: + case ILOpCode.Ldlen: return Push(new LdLen(StackType.I, Pop())); - case Cil.Code.Ldobj: + case ILOpCode.Ldobj: return Push(new LdObj(PopPointer(), ReadAndDecodeTypeReference())); - case Cil.Code.Ldsfld: + case ILOpCode.Ldsfld: { var field = ReadAndDecodeFieldReference(); return Push(new LdObj(new LdsFlda(field), field.Type)); } - case Cil.Code.Ldsflda: + case ILOpCode.Ldsflda: return Push(new LdsFlda(ReadAndDecodeFieldReference())); - case Cil.Code.Stsfld: + case ILOpCode.Stsfld: { var field = ReadAndDecodeFieldReference(); return new StObj(value: Pop(field.Type.GetStackType()), target: new LdsFlda(field), type: field.Type); } - case Cil.Code.Ldtoken: + case ILOpCode.Ldtoken: return Push(LdToken(ReadAndDecodeMetadataToken())); - case Cil.Code.Ldvirtftn: + case ILOpCode.Ldvirtftn: return Push(new LdVirtFtn(Pop(), ReadAndDecodeMethodReference())); - case Cil.Code.Mkrefany: + case ILOpCode.Mkrefany: return Push(new MakeRefAny(PopPointer(), ReadAndDecodeTypeReference())); - case Cil.Code.Newarr: + case ILOpCode.Newarr: return Push(new NewArr(ReadAndDecodeTypeReference(), Pop())); - case Cil.Code.Refanytype: + case ILOpCode.Refanytype: return Push(new RefAnyType(Pop())); - case Cil.Code.Refanyval: + case ILOpCode.Refanyval: return Push(new RefAnyValue(Pop(), ReadAndDecodeTypeReference())); - case Cil.Code.Rethrow: + case ILOpCode.Rethrow: return new Rethrow(); - case Cil.Code.Sizeof: + case ILOpCode.Sizeof: return Push(new SizeOf(ReadAndDecodeTypeReference())); - case Cil.Code.Stelem_Any: + case ILOpCode.Stelem: return StElem(ReadAndDecodeTypeReference()); - case Cil.Code.Stelem_I1: + case ILOpCode.Stelem_i1: return StElem(compilation.FindType(KnownTypeCode.SByte)); - case Cil.Code.Stelem_I2: + case ILOpCode.Stelem_i2: return StElem(compilation.FindType(KnownTypeCode.Int16)); - case Cil.Code.Stelem_I4: + case ILOpCode.Stelem_i4: return StElem(compilation.FindType(KnownTypeCode.Int32)); - case Cil.Code.Stelem_I8: + case ILOpCode.Stelem_i8: return StElem(compilation.FindType(KnownTypeCode.Int64)); - case Cil.Code.Stelem_R4: + case ILOpCode.Stelem_r4: return StElem(compilation.FindType(KnownTypeCode.Single)); - case Cil.Code.Stelem_R8: + case ILOpCode.Stelem_r8: return StElem(compilation.FindType(KnownTypeCode.Double)); - case Cil.Code.Stelem_I: + case ILOpCode.Stelem_i: return StElem(compilation.FindType(KnownTypeCode.IntPtr)); - case Cil.Code.Stelem_Ref: + case ILOpCode.Stelem_ref: return StElem(compilation.FindType(KnownTypeCode.Object)); - case Cil.Code.Stobj: + case ILOpCode.Stobj: { var type = ReadAndDecodeTypeReference(); return new StObj(value: Pop(type.GetStackType()), target: PopPointer(), type: type); } - case Cil.Code.Throw: + case ILOpCode.Throw: return new Throw(Pop()); - case Cil.Code.Unbox: + case ILOpCode.Unbox: return Push(new Unbox(Pop(), ReadAndDecodeTypeReference())); - case Cil.Code.Unbox_Any: + case ILOpCode.Unbox_any: return Push(new UnboxAny(Pop(), ReadAndDecodeTypeReference())); default: - return new InvalidBranch("Unknown opcode: " + cecilInst.OpCode.ToString()); + return new InvalidBranch("Unknown opcode: " + opCode.ToString()); } } @@ -1001,15 +1008,10 @@ namespace ICSharpCode.Decompiler.IL return new StLoc(v, inst); } - Interval GetCurrentInstructionInterval() - { - return new Interval(currentInstruction.Offset, currentInstruction.GetEndOffset()); - } - ILInstruction Peek() { if (currentStack.IsEmpty) { - return new InvalidExpression("Stack underflow") { ILRange = GetCurrentInstructionInterval() }; + return new InvalidExpression("Stack underflow") { ILRange = new Interval(reader.Offset, reader.Offset) }; } return new LdLoc(currentStack.Peek()); } @@ -1017,7 +1019,7 @@ namespace ICSharpCode.Decompiler.IL ILInstruction Pop() { if (currentStack.IsEmpty) { - return new InvalidExpression("Stack underflow") { ILRange = GetCurrentInstructionInterval() }; + return new InvalidExpression("Stack underflow") { ILRange = new Interval(reader.Offset, reader.Offset) }; } ILVariable v; currentStack = currentStack.Pop(out v); @@ -1117,7 +1119,7 @@ namespace ICSharpCode.Decompiler.IL private ILInstruction DecodeLdstr() { - return new LdStr((string)currentInstruction.Operand); + return new LdStr(ILParser.DecodeUserString(ref reader, metadata)); } private ILInstruction Ldarg(int v) @@ -1198,7 +1200,7 @@ namespace ICSharpCode.Decompiler.IL private ILInstruction DecodeUnaligned() { - byte alignment = (byte)currentInstruction.Operand; + byte alignment = reader.ReadByte(); var inst = DecodeInstruction(); var sup = UnpackPush(inst) as ISupportsUnalignedPrefix; if (sup != null) @@ -1277,18 +1279,20 @@ namespace ICSharpCode.Decompiler.IL ILInstruction DecodeCallIndirect() { + var standaloneSignature = metadata.GetStandaloneSignature((StandaloneSignatureHandle)ReadAndDecodeMetadataToken()); + Debug.Assert(standaloneSignature.GetKind() == StandaloneSignatureKind.Method); + var signature = standaloneSignature.DecodeMethodSignature(new TypeSystem.Implementation.TypeReferenceSignatureDecoder(), default); var functionPointer = Pop(StackType.I); - var signature = (CallSite)currentInstruction.Operand; - Debug.Assert(!signature.HasThis); - var parameterTypes = new IType[signature.Parameters.Count]; + Debug.Assert(!signature.Header.IsInstance); + var parameterTypes = new IType[signature.ParameterTypes.Length]; var arguments = new ILInstruction[parameterTypes.Length]; - for (int i = signature.Parameters.Count - 1; i >= 0; i--) { - parameterTypes[i] = typeSystem.Resolve(signature.Parameters[i].ParameterType); + for (int i = signature.ParameterTypes.Length - 1; i >= 0; i--) { + parameterTypes[i] = signature.ParameterTypes[i].Resolve(resolveContext); arguments[i] = Pop(parameterTypes[i].GetStackType()); } var call = new CallIndirect( - signature.CallingConvention, - typeSystem.Resolve(signature.ReturnType), + signature.Header.CallingConvention, + signature.ReturnType.Resolve(resolveContext), parameterTypes.ToImmutableArray(), arguments, functionPointer @@ -1299,14 +1303,6 @@ namespace ICSharpCode.Decompiler.IL return call; } - static int GetPopCount(OpCode callCode, MethodReference methodReference) - { - int popCount = methodReference.Parameters.Count; - if (callCode != OpCode.NewObj && methodReference.HasThis) - popCount++; - return popCount; - } - static int GetPopCount(OpCode callCode, IMethod method) { int popCount = method.Parameters.Count; @@ -1360,30 +1356,25 @@ namespace ICSharpCode.Decompiler.IL } } - int? DecodeBranchTarget(bool shortForm) - { -// int target = shortForm ? reader.ReadSByte() : reader.ReadInt32(); -// target += reader.Position; -// return target; - return ((Cil.Instruction)currentInstruction.Operand)?.Offset; - } + bool IsInvalidBranch(int target) => target < 0 || target >= reader.Length; - ILInstruction DecodeComparisonBranch(bool shortForm, ComparisonKind kind, bool un = false) + ILInstruction DecodeComparisonBranch(ILOpCode opCode, ComparisonKind kind, bool un = false) { - int? target = DecodeBranchTarget(shortForm); + int start = reader.Offset - 1; // opCode is always one byte in this case + int target = ILParser.DecodeBranchTarget(ref reader, opCode); var condition = Comparison(kind, un); - condition.ILRange = GetCurrentInstructionInterval(); - if (target != null) { - MarkBranchTarget(target.Value); - return new IfInstruction(condition, new Branch(target.Value)); + condition.ILRange = new Interval(start, reader.Offset); + if (!IsInvalidBranch(target)) { + MarkBranchTarget(target); + return new IfInstruction(condition, new Branch(target)); } else { return new IfInstruction(condition, new InvalidBranch("Invalid branch target")); } } - ILInstruction DecodeConditionalBranch(bool shortForm, bool negate) + ILInstruction DecodeConditionalBranch(ILOpCode opCode, bool negate) { - int? target = DecodeBranchTarget(shortForm); + int target = ILParser.DecodeBranchTarget(ref reader, opCode); ILInstruction condition = Pop(); switch (condition.ResultType) { case StackType.O: @@ -1422,23 +1413,23 @@ namespace ICSharpCode.Decompiler.IL } break; } - if (target != null) { - MarkBranchTarget(target.Value); - return new IfInstruction(condition, new Branch(target.Value)); + if (!IsInvalidBranch(target)) { + MarkBranchTarget(target); + return new IfInstruction(condition, new Branch(target)); } else { return new IfInstruction(condition, new InvalidBranch("Invalid branch target")); } } - ILInstruction DecodeUnconditionalBranch(bool shortForm, bool isLeave = false) + ILInstruction DecodeUnconditionalBranch(ILOpCode opCode, bool isLeave = false) { - int? target = DecodeBranchTarget(shortForm); + int target = ILParser.DecodeBranchTarget(ref reader, opCode); if (isLeave) { currentStack = currentStack.Clear(); } - if (target != null) { - MarkBranchTarget(target.Value); - return new Branch(target.Value); + if (!IsInvalidBranch(target)) { + MarkBranchTarget(target); + return new Branch(target); } else { return new InvalidBranch("Invalid branch target"); } @@ -1452,25 +1443,23 @@ namespace ICSharpCode.Decompiler.IL ILInstruction DecodeSwitch() { -// uint length = reader.ReadUInt32(); -// int baseOffset = 4 * (int)length + reader.Position; - var labels = (Cil.Instruction[])currentInstruction.Operand; + var targets = ILParser.DecodeSwitchTargets(ref reader); var instr = new SwitchInstruction(Pop(StackType.I4)); - for (int i = 0; i < labels.Length; i++) { + for (int i = 0; i < targets.Length; i++) { var section = new SwitchSection(); section.Labels = new LongSet(i); - int? target = labels[i]?.Offset; // baseOffset + reader.ReadInt32(); - if (target != null) { - MarkBranchTarget(target.Value); - section.Body = new Branch(target.Value); + int target = targets[i]; + if (!IsInvalidBranch(target)) { + MarkBranchTarget(target); + section.Body = new Branch(target); } else { section.Body = new InvalidBranch("Invalid branch target"); } instr.Sections.Add(section); } var defaultSection = new SwitchSection(); - defaultSection.Labels = new LongSet(new LongInterval(0, labels.Length)).Invert(); + defaultSection.Labels = new LongSet(new LongInterval(0, targets.Length)).Invert(); defaultSection.Body = new Nop(); instr.Sections.Add(defaultSection); return instr; @@ -1507,14 +1496,12 @@ namespace ICSharpCode.Decompiler.IL return new Leave(mainContainer, call); } - ILInstruction LdToken(IMetadataTokenProvider token) + ILInstruction LdToken(EntityHandle token) { - if (token is TypeReference) - return new LdTypeToken(typeSystem.Resolve((TypeReference)token)); - if (token is FieldReference) - return new LdMemberToken(typeSystem.Resolve((FieldReference)token)); - if (token is MethodReference) - return new LdMemberToken(typeSystem.Resolve((MethodReference)token)); + if (token.Kind.IsTypeKind()) + return new LdTypeToken(typeSystem.ResolveAsType(token)); + if (token.Kind.IsMemberKind()) + return new LdMemberToken(typeSystem.ResolveAsMember(token)); throw new NotImplementedException(); } } diff --git a/ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs b/ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs index a2380d5cf..6deb6a8ce 100644 --- a/ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs +++ b/ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs @@ -33,7 +33,7 @@ namespace ICSharpCode.Decompiler.IL public readonly InstructionCollection Arguments; ILInstruction functionPointer; - public Mono.Cecil.MethodCallingConvention CallingConvention { get; } + public System.Reflection.Metadata.SignatureCallingConvention CallingConvention { get; } public IType ReturnType { get; } public ImmutableArray ParameterTypes { get; } @@ -61,7 +61,7 @@ namespace ICSharpCode.Decompiler.IL functionPointer.ChildIndex = Arguments.Count; } - public CallIndirect(Mono.Cecil.MethodCallingConvention callingConvention, IType returnType, ImmutableArray parameterTypes, + public CallIndirect(System.Reflection.Metadata.SignatureCallingConvention callingConvention, IType returnType, ImmutableArray parameterTypes, IEnumerable arguments, ILInstruction functionPointer) : base(OpCode.CallIndirect) { this.CallingConvention = callingConvention; diff --git a/ICSharpCode.Decompiler/Metadata/Dom.cs b/ICSharpCode.Decompiler/Metadata/Dom.cs index 27f8ec7d6..dcfc5ba53 100644 --- a/ICSharpCode.Decompiler/Metadata/Dom.cs +++ b/ICSharpCode.Decompiler/Metadata/Dom.cs @@ -76,6 +76,7 @@ namespace ICSharpCode.Decompiler.Metadata { IList GetSequencePoints(MethodDefinition method); IList GetVariables(MethodDefinition method); + bool TryGetName(MethodDefinition method, int index, out string name); } public class PEFile @@ -301,7 +302,7 @@ namespace ICSharpCode.Decompiler.Metadata } } - public struct AssemblyReference : IAssemblyReference + public struct AssemblyReference : IAssemblyReference, IEquatable { static readonly SHA1 sha1 = SHA1.Create(); @@ -332,6 +333,26 @@ namespace ICSharpCode.Decompiler.Metadata return bytes; } + public bool Equals(AssemblyReference other) + { + return Module == other.Module && Handle == other.Handle; + } + + public override bool Equals(object obj) + { + if (obj is AssemblyReference reference) + return Equals(reference); + return false; + } + + public override int GetHashCode() + { + return unchecked(982451629 * Module.GetHashCode() + 982451653 * MetadataTokens.GetToken(Handle)); + } + + public static bool operator ==(AssemblyReference lhs, AssemblyReference rhs) => lhs.Equals(rhs); + public static bool operator !=(AssemblyReference lhs, AssemblyReference rhs) => !lhs.Equals(rhs); + public AssemblyReference(PEFile module, AssemblyReferenceHandle handle) { Module = module; @@ -358,9 +379,14 @@ namespace ICSharpCode.Decompiler.Metadata return MetadataResolver.ResolveType(Handle, new SimpleMetadataResolveContext(Module)); } + public FieldDefinition ResolveAsField() + { + return MetadataResolver.ResolveAsField(Handle, new SimpleMetadataResolveContext(Module)); + } + public MethodDefinition ResolveAsMethod() { - return MetadataResolver.ResolveMember(Handle, new SimpleMetadataResolveContext(Module)); + return MetadataResolver.ResolveAsMethod(Handle, new SimpleMetadataResolveContext(Module)); } public bool Equals(Entity other) @@ -717,7 +743,7 @@ namespace ICSharpCode.Decompiler.Metadata public FullTypeName FullName { get { - return DecodeSignature(new FullTypeNameSignatureDecoder(Module.GetMetadataReader()), default(Unit)); + return DecodeSignature(new FullTypeNameSignatureDecoder(Module.GetMetadataReader()), default); } } @@ -785,7 +811,7 @@ namespace ICSharpCode.Decompiler.Metadata public FullTypeName GetFunctionPointerType(MethodSignature signature) { - return default(FullTypeName); + return default; } public FullTypeName GetGenericInstantiation(FullTypeName genericType, ImmutableArray typeArguments) @@ -795,12 +821,12 @@ namespace ICSharpCode.Decompiler.Metadata public FullTypeName GetGenericMethodParameter(Unit genericContext, int index) { - return default(FullTypeName); + return default; } public FullTypeName GetGenericTypeParameter(Unit genericContext, int index) { - return default(FullTypeName); + return default; } public FullTypeName GetModifiedType(FullTypeName modifier, FullTypeName unmodifiedType, bool isRequired) @@ -840,7 +866,7 @@ namespace ICSharpCode.Decompiler.Metadata public FullTypeName GetTypeFromSpecification(MetadataReader reader, Unit genericContext, TypeSpecificationHandle handle, byte rawTypeKind) { - return reader.GetTypeSpecification(handle).DecodeSignature(new FullTypeNameSignatureDecoder(metadata), default(Unit)); + return reader.GetTypeSpecification(handle).DecodeSignature(new FullTypeNameSignatureDecoder(metadata), default); } } diff --git a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs index a94ea155e..7dccf550b 100644 --- a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs +++ b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs @@ -23,8 +23,27 @@ namespace ICSharpCode.Decompiler.Metadata { return new Entity(module, entity).ResolveAsType(); } + + public static FieldDefinition ResolveAsField(this EntityHandle entity, PEFile module) + { + return new Entity(module, entity).ResolveAsField(); + } + + public static MethodDefinition ResolveAsMethod(this EntityHandle entity, PEFile module) + { + return new Entity(module, entity).ResolveAsMethod(); + } #endregion + public static MethodDefinition AsMethod(this IMetadataEntity entity) + { + if (entity is MethodDefinition method) + return method; + if (entity is Entity e) + return e; + throw new NotSupportedException(); + } + public static bool IsNil(this IAssemblyReference reference) { return reference == null || (reference is Metadata.AssemblyReference ar && ar.IsNil); @@ -121,7 +140,7 @@ namespace ICSharpCode.Decompiler.Metadata case HandleKind.AssemblyReference: return (AssemblyReferenceHandle)tr.ResolutionScope; default: - return default(AssemblyReferenceHandle); + return default; } } @@ -374,5 +393,19 @@ namespace ICSharpCode.Decompiler.Metadata return metadata.GetAssemblyDefinition(); return null; } + + public unsafe static ParameterHandle At(this ParameterHandleCollection collection, MetadataReader metadata, int index) + { + if (metadata.GetTableRowCount(TableIndex.ParamPtr) > 0) { + int rowSize = metadata.GetTableRowSize(TableIndex.ParamPtr); + int paramRefSize = (metadata.GetReferenceSize(TableIndex.ParamPtr) > 2) ? 4 : metadata.GetReferenceSize(TableIndex.Param); + int offset = metadata.GetTableMetadataOffset(TableIndex.ParamPtr) + index * rowSize; + byte* ptr = metadata.MetadataPointer + offset; + if (paramRefSize == 2) + return MetadataTokens.ParameterHandle(*(ushort*)ptr); + return MetadataTokens.ParameterHandle((int)*(uint*)ptr); + } + return MetadataTokens.ParameterHandle((index + 1) & 0xFFFFFF); + } } } diff --git a/ICSharpCode.Decompiler/Metadata/MetadataResolver.cs b/ICSharpCode.Decompiler/Metadata/MetadataResolver.cs index efeac66fa..871f218ec 100644 --- a/ICSharpCode.Decompiler/Metadata/MetadataResolver.cs +++ b/ICSharpCode.Decompiler/Metadata/MetadataResolver.cs @@ -57,12 +57,34 @@ namespace ICSharpCode.Decompiler.Metadata } } - public static MethodDefinition ResolveMember(EntityHandle handle, IMetadataResolveContext context) + public static MethodDefinition ResolveAsMethod(EntityHandle handle, IMetadataResolveContext context) { switch (handle.Kind) { case HandleKind.MethodDefinition: return new MethodDefinition(context.CurrentModule, (MethodDefinitionHandle)handle); case HandleKind.MemberReference: + var memberRefHandle = (MemberReferenceHandle)handle; + var metadata = context.CurrentModule.GetMetadataReader(); + var memberRef = metadata.GetMemberReference(memberRefHandle); + if (memberRef.GetKind() != MemberReferenceKind.Method) + return default; + break; + } + throw new NotImplementedException(); + } + + public static FieldDefinition ResolveAsField(EntityHandle handle, IMetadataResolveContext context) + { + switch (handle.Kind) { + case HandleKind.FieldDefinition: + return new FieldDefinition(context.CurrentModule, (FieldDefinitionHandle)handle); + case HandleKind.MemberReference: + var memberRefHandle = (MemberReferenceHandle)handle; + var metadata = context.CurrentModule.GetMetadataReader(); + var memberRef = metadata.GetMemberReference(memberRefHandle); + if (memberRef.GetKind() != MemberReferenceKind.Field) + throw new ArgumentException("MemberReferenceKind must be Field!", nameof(handle)); + break; } throw new NotImplementedException(); diff --git a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs index d0c767c80..982758c1b 100644 --- a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs +++ b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs @@ -61,7 +61,7 @@ namespace ICSharpCode.Decompiler.Metadata { var resolver = new UniversalAssemblyResolver(mainAssemblyFileName, throwOnError); - var module = new PEReader(new FileStream(mainAssemblyFileName, FileMode.Open)); + var module = new PEReader(new FileStream(mainAssemblyFileName, FileMode.Open), inMemory ? PEStreamOptions.PrefetchEntireImage : PEStreamOptions.Default); resolver.TargetFramework = module.DetectTargetFrameworkId(); diff --git a/ICSharpCode.Decompiler/SRMExtensions.cs b/ICSharpCode.Decompiler/SRMExtensions.cs index 7695d5ee2..85e931051 100644 --- a/ICSharpCode.Decompiler/SRMExtensions.cs +++ b/ICSharpCode.Decompiler/SRMExtensions.cs @@ -16,6 +16,10 @@ namespace ICSharpCode.Decompiler public static bool HasFlag(this PropertyDefinition propertyDefinition, PropertyAttributes attribute) => (propertyDefinition.Attributes & attribute) == attribute; public static bool HasFlag(this EventDefinition eventDefinition, EventAttributes attribute) => (eventDefinition.Attributes & attribute) == attribute; + public static bool IsTypeKind(this HandleKind kind) => kind == HandleKind.TypeDefinition || kind == HandleKind.TypeReference || kind == HandleKind.TypeSpecification; + public static bool IsMemberKind(this HandleKind kind) => kind == HandleKind.MethodDefinition || kind == HandleKind.PropertyDefinition || kind == HandleKind.FieldDefinition + || kind == HandleKind.EventDefinition || kind == HandleKind.MemberReference || kind == HandleKind.MethodSpecification; + public static bool IsValueType(this TypeDefinitionHandle handle, MetadataReader reader) { return reader.GetTypeDefinition(handle).IsValueType(reader); diff --git a/ICSharpCode.Decompiler/SRMHacks.cs b/ICSharpCode.Decompiler/SRMHacks.cs index 67bbc46e0..b278ded0f 100644 --- a/ICSharpCode.Decompiler/SRMHacks.cs +++ b/ICSharpCode.Decompiler/SRMHacks.cs @@ -32,31 +32,19 @@ namespace ICSharpCode.Decompiler return 0; } - public static unsafe ImmutableArray GetMethodImplementations(this MethodDefinitionHandle handle, MetadataReader reader) + public static ImmutableArray GetMethodImplementations(this MethodDefinitionHandle handle, MetadataReader reader) { - byte* startPointer = reader.MetadataPointer; - int offset = reader.GetTableMetadataOffset(TableIndex.MethodImpl); - int rowSize = reader.GetTableRowSize(TableIndex.MethodImpl); - int rowCount = reader.GetTableRowCount(TableIndex.MethodImpl); - var methodDefSize = reader.GetReferenceSize(TableIndex.MethodDef); - var typeDefSize = reader.GetReferenceSize(TableIndex.TypeDef); - - var containingTypeRow = reader.GetRowNumber(reader.GetMethodDefinition(handle).GetDeclaringType()); - var methodDefRow = reader.GetRowNumber(handle); - - var list = new List(); + var resultBuilder = ImmutableArray.CreateBuilder(); + var typeDefinition = reader.GetTypeDefinition(reader.GetMethodDefinition(handle).GetDeclaringType()); - // TODO : if sorted -> binary search? - for (int row = 0; row < reader.GetTableRowCount(TableIndex.MethodImpl); row++) { - byte* ptr = startPointer + offset + rowSize * row; - uint currentTypeRow = typeDefSize == 2 ? *(ushort*)ptr : *(uint*)ptr; - if (currentTypeRow != containingTypeRow) continue; - uint currentMethodRowCoded = methodDefSize == 2 ? *(ushort*)(ptr + typeDefSize) : *(uint*)(ptr + typeDefSize); - if ((currentMethodRowCoded >> 1) != methodDefRow) continue; - list.Add(MetadataTokens.MethodImplementationHandle(row + 1)); + foreach (var methodImplementationHandle in typeDefinition.GetMethodImplementations()) { + var methodImplementation = reader.GetMethodImplementation(methodImplementationHandle); + if (methodImplementation.MethodBody == handle) { + resultBuilder.Add(methodImplementationHandle); + } } - return list.ToImmutableArray(); + return resultBuilder.ToImmutable(); } /* diff --git a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs index 9efc2e9e8..2a8467a7e 100644 --- a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs +++ b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs @@ -1,9 +1,12 @@ using System; using System.Collections.Generic; using System.Linq; +using SRM = System.Reflection.Metadata; using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.Util; -using Mono.Cecil; + +using static ICSharpCode.Decompiler.Metadata.MetadataExtensions; +using System.Diagnostics; namespace ICSharpCode.Decompiler.TypeSystem { @@ -15,7 +18,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// public class DecompilerTypeSystem : IDecompilerTypeSystem { - readonly ModuleDefinition moduleDefinition; + readonly Metadata.PEFile moduleDefinition; readonly ICompilation compilation; readonly ITypeResolveContext context; @@ -29,36 +32,38 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Dictionary for NRefactory->Cecil lookup. /// May only be accessed within lock(entityDict) /// - Dictionary entityDict = new Dictionary(); + Dictionary entityDict = new Dictionary(); - Dictionary fieldLookupCache = new Dictionary(); - Dictionary propertyLookupCache = new Dictionary(); - Dictionary methodLookupCache = new Dictionary(); - Dictionary eventLookupCache = new Dictionary(); + Dictionary fieldLookupCache = new Dictionary(); + Dictionary propertyLookupCache = new Dictionary(); + Dictionary methodLookupCache = new Dictionary(); + Dictionary eventLookupCache = new Dictionary(); - public DecompilerTypeSystem(ModuleDefinition moduleDefinition) + public DecompilerTypeSystem(Metadata.PEFile moduleDefinition) { if (moduleDefinition == null) throw new ArgumentNullException(nameof(moduleDefinition)); this.moduleDefinition = moduleDefinition; - /*MetadataLoader cecilLoader = new MetadataLoader { IncludeInternalMembers = true, LazyLoad = true, OnEntityLoaded = StoreMemberReference, ShortenInterfaceImplNames = false }; - typeReferenceCecilLoader.SetCurrentModule(moduleDefinition); - IUnresolvedAssembly mainAssembly = cecilLoader.LoadModule(moduleDefinition); + MetadataLoader cecilLoader = new MetadataLoader { IncludeInternalMembers = true, LazyLoad = true, OnEntityLoaded = StoreMemberReference, ShortenInterfaceImplNames = false }; + typeReferenceCecilLoader.SetCurrentModule(moduleDefinition.GetMetadataReader()); + IUnresolvedAssembly mainAssembly = cecilLoader.LoadModule(moduleDefinition.GetMetadataReader()); // Load referenced assemblies and type-forwarder references. // This is necessary to make .NET Core/PCL binaries work better. var referencedAssemblies = new List(); - var assemblyReferenceQueue = new Queue(moduleDefinition.AssemblyReferences); - var processedAssemblyReferences = new HashSet(KeyComparer.Create((AssemblyNameReference reference) => reference.FullName)); + var assemblyReferenceQueue = new Queue(moduleDefinition.AssemblyReferences); + var processedAssemblyReferences = new HashSet(KeyComparer.Create((Metadata.AssemblyReference reference) => reference.FullName)); while (assemblyReferenceQueue.Count > 0) { var asmRef = assemblyReferenceQueue.Dequeue(); if (!processedAssemblyReferences.Add(asmRef)) continue; var asm = moduleDefinition.AssemblyResolver.Resolve(asmRef); if (asm != null) { - referencedAssemblies.Add(cecilLoader.LoadAssembly(asm)); - foreach (var forwarder in asm.MainModule.ExportedTypes) { - if (!forwarder.IsForwarder || !(forwarder.Scope is AssemblyNameReference forwarderRef)) continue; - assemblyReferenceQueue.Enqueue(forwarderRef); + referencedAssemblies.Add(cecilLoader.LoadModule(asm.GetMetadataReader())); + var metadata = asm.GetMetadataReader(); + foreach (var h in metadata.ExportedTypes) { + var forwarder = metadata.GetExportedType(h); + if (!forwarder.IsForwarder || forwarder.Implementation.Kind != SRM.HandleKind.AssemblyReference) continue; + assemblyReferenceQueue.Enqueue(new Metadata.AssemblyReference(asm, (SRM.AssemblyReferenceHandle)forwarder.Implementation)); } } } @@ -69,7 +74,7 @@ namespace ICSharpCode.Decompiler.TypeSystem referencedAssemblies.Add(MinimalCorlib.Instance); compilation = new SimpleCompilation(mainAssembly, referencedAssemblies); } - context = new SimpleTypeResolveContext(compilation.MainAssembly);*/ + context = new SimpleTypeResolveContext(compilation.MainAssembly); } public ICompilation Compilation { @@ -80,30 +85,24 @@ namespace ICSharpCode.Decompiler.TypeSystem get { return compilation.MainAssembly; } } - public ModuleDefinition ModuleDefinition { + public Metadata.PEFile ModuleDefinition { get { return moduleDefinition; } } - void StoreMemberReference(IUnresolvedEntity entity, MemberReference mr) + void StoreMemberReference(IUnresolvedEntity entity, SRM.EntityHandle mr) { // This is a callback from the type system, which is multi-threaded and may be accessed externally lock (entityDict) entityDict[entity] = mr; } - /// - /// Retrieves the Cecil member definition for the specified member. - /// - /// - /// Returns null if the member is not defined in the module being decompiled. - /// - public MemberReference GetCecil(IUnresolvedEntity member) + /* + Metadata.IMetadataEntity GetMetadata(IUnresolvedEntity member) { if (member == null) return null; lock (entityDict) { - MemberReference mr; - if (entityDict.TryGetValue(member, out mr)) + if (entityDict.TryGetValue(member, out var mr)) return mr; return null; } @@ -115,62 +114,90 @@ namespace ICSharpCode.Decompiler.TypeSystem /// /// Returns null if the member is not defined in the module being decompiled. /// - public MemberReference GetCecil(IMember member) + public Metadata.IMetadataEntity GetMetadata(IMember member) { if (member == null) return null; - return GetCecil(member.UnresolvedMember); + return GetMetadata(member.UnresolvedMember); } + /// /// Retrieves the Cecil type definition. /// /// /// Returns null if the type is not defined in the module being decompiled. /// - public TypeDefinition GetCecil(ITypeDefinition typeDefinition) + public Metadata.TypeDefinition GetMetadata(ITypeDefinition typeDefinition) { if (typeDefinition == null) - return null; - return GetCecil(typeDefinition.Parts[0]) as TypeDefinition; + return default; + return (Metadata.TypeDefinition)GetMetadata(typeDefinition.Parts[0]); } + */ - #region Resolve Type - public IType Resolve(TypeReference typeReference) + + public IMember ResolveAsMember(SRM.EntityHandle memberReference) { throw new NotImplementedException(); -#if false - if (typeReference == null) + } + + #region Resolve Type + public IType ResolveAsType(SRM.EntityHandle typeReference) + { + if (typeReference.IsNil) return SpecialType.UnknownType; - // We need to skip SentinelType and PinnedType. - // But PinnedType can be nested within modopt, so we'll also skip those. - while (typeReference is OptionalModifierType || typeReference is RequiredModifierType) { - typeReference = ((TypeSpecification)typeReference).ElementType; - } - if (typeReference is SentinelType || typeReference is Mono.Cecil.PinnedType) { - typeReference = ((TypeSpecification)typeReference).ElementType; - } ITypeReference typeRef; lock (typeReferenceCecilLoader) typeRef = typeReferenceCecilLoader.ReadTypeReference(typeReference); return typeRef.Resolve(context); -#endif } -#endregion + #endregion #region Resolve Field - public IField Resolve(FieldReference fieldReference) + public IField ResolveAsField(SRM.EntityHandle fieldReference) { - if (fieldReference == null) + if (fieldReference.IsNil) throw new ArgumentNullException(nameof(fieldReference)); + if (fieldReference.Kind != SRM.HandleKind.FieldDefinition && fieldReference.Kind != SRM.HandleKind.MemberReference) + throw new ArgumentException("HandleKind must be either FieldDefinition or MemberReference", nameof(fieldReference)); lock (fieldLookupCache) { IField field; if (!fieldLookupCache.TryGetValue(fieldReference, out field)) { - field = FindNonGenericField(fieldReference); - if (fieldReference.DeclaringType.IsGenericInstance) { - var git = (GenericInstanceType)fieldReference.DeclaringType; - var typeArguments = git.GenericArguments.SelectArray(Resolve); - field = (IField)field.Specialize(new TypeParameterSubstitution(typeArguments, null)); + var metadata = moduleDefinition.GetMetadataReader(); + IType declaringType; + ITypeReference returnType; + switch (fieldReference.Kind) { + case SRM.HandleKind.FieldDefinition: + var fieldDef = metadata.GetFieldDefinition((SRM.FieldDefinitionHandle)fieldReference); + declaringType = ResolveAsType(fieldDef.GetDeclaringType()); + returnType = fieldDef.DecodeSignature(new TypeReferenceSignatureDecoder(), default); + var declaringTypeDefinition = declaringType.GetDefinition(); + if (declaringTypeDefinition == null) + field = CreateFakeField(declaringType, metadata.GetString(fieldDef.Name), returnType); + else { + field = declaringTypeDefinition.GetFields(f => f.MetadataToken == fieldReference, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault() + ?? CreateFakeField(declaringType, metadata.GetString(fieldDef.Name), returnType); + } + break; + case SRM.HandleKind.MemberReference: + var memberRef = metadata.GetMemberReference((SRM.MemberReferenceHandle)fieldReference); + switch (memberRef.Parent.Kind) { + case SRM.HandleKind.TypeReference: + declaringType = ResolveAsType(memberRef.Parent); + field = FindNonGenericField(metadata, memberRef, declaringType); + break; + case SRM.HandleKind.TypeSpecification: + throw new NotImplementedException(); + /*if (fieldReference.DeclaringType.IsGenericInstance) { + var git = (GenericInstanceType)fieldReference.DeclaringType; + var typeArguments = git.GenericArguments.SelectArray(Resolve); + field = (IField)field.Specialize(new TypeParameterSubstitution(typeArguments, null)); + }*/ + default: + throw new NotSupportedException(); + } + break; } fieldLookupCache.Add(fieldReference, field); } @@ -178,29 +205,26 @@ namespace ICSharpCode.Decompiler.TypeSystem } } - IField FindNonGenericField(FieldReference fieldReference) + IField FindNonGenericField(SRM.MetadataReader metadata, SRM.MemberReference memberRef, IType declaringType) { - ITypeDefinition typeDef = Resolve(fieldReference.DeclaringType).GetDefinition(); + string name = metadata.GetString(memberRef.Name); + ITypeDefinition typeDef = declaringType.GetDefinition(); + ITypeReference returnType = memberRef.DecodeFieldSignature(new TypeReferenceSignatureDecoder(), default); + if (typeDef == null) - return CreateFakeField(fieldReference); + return CreateFakeField(declaringType, name, returnType); foreach (IField field in typeDef.Fields) - if (field.Name == fieldReference.Name) + if (field.Name == name) return field; - return CreateFakeField(fieldReference); + return CreateFakeField(declaringType, name, returnType); } - IField CreateFakeField(FieldReference fieldReference) + IField CreateFakeField(IType declaringType, string name, ITypeReference returnType) { - throw new NotImplementedException(); -#if false - var declaringType = Resolve(fieldReference.DeclaringType); var f = new DefaultUnresolvedField(); - f.Name = fieldReference.Name; - lock (typeReferenceCecilLoader) { - f.ReturnType = typeReferenceCecilLoader.ReadTypeReference(fieldReference.FieldType); - } + f.Name = name; + f.ReturnType = returnType; return new ResolvedFakeField(f, context.WithCurrentTypeDefinition(declaringType.GetDefinition()), declaringType); -#endif } class ResolvedFakeField : DefaultResolvedField @@ -218,79 +242,114 @@ namespace ICSharpCode.Decompiler.TypeSystem get { return declaringType; } } } -#endregion + #endregion #region Resolve Method - public IMethod Resolve(MethodReference methodReference) + public IMethod ResolveAsMethod(SRM.EntityHandle methodReference) { - if (methodReference == null) + if (methodReference.IsNil) throw new ArgumentNullException(nameof(methodReference)); + if (methodReference.Kind != SRM.HandleKind.MethodDefinition && methodReference.Kind != SRM.HandleKind.MemberReference && methodReference.Kind != SRM.HandleKind.MethodSpecification) + throw new ArgumentException("HandleKind must be either a MethodDefinition, MemberReference or MethodSpecification", nameof(methodReference)); lock (methodLookupCache) { IMethod method; if (!methodLookupCache.TryGetValue(methodReference, out method)) { - method = FindNonGenericMethod(methodReference.GetElementMethod()); - if (methodReference.CallingConvention == MethodCallingConvention.VarArg) { + var metadata = moduleDefinition.GetMetadataReader(); + IType declaringType; + switch (methodReference.Kind) { + case SRM.HandleKind.MethodDefinition: + var methodDef = metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)methodReference); + declaringType = ResolveAsType(methodDef.GetDeclaringType()); + var declaringTypeDefinition = declaringType.GetDefinition(); + if (declaringTypeDefinition == null) + method = CreateFakeMethod(declaringType, metadata.GetString(methodDef.Name), methodDef.DecodeSignature(new TypeReferenceSignatureDecoder(), default)); + else { + method = (IMethod)declaringTypeDefinition.GetMembers(m => m.MetadataToken == methodReference, GetMemberOptions.IgnoreInheritedMembers).FirstOrDefault() + ?? CreateFakeMethod(declaringType, metadata.GetString(methodDef.Name), methodDef.DecodeSignature(new TypeReferenceSignatureDecoder(), default)); + } + break; + case SRM.HandleKind.MemberReference: + var memberRef = metadata.GetMemberReference((SRM.MemberReferenceHandle)methodReference); + break; + case SRM.HandleKind.MethodSpecification: + break; + } + + /*method = FindNonGenericMethod(metadata, new Metadata.Entity(moduleDefinition, methodReference).ResolveAsMethod(), signature); + switch (methodReference.Kind) { + case SRM.HandleKind.StandaloneSignature: + var standaloneSignature = metadata.GetStandaloneSignature((SRM.StandaloneSignatureHandle)methodReference); + Debug.Assert(standaloneSignature.GetKind() == SRM.StandaloneSignatureKind.Method); + var signature = standaloneSignature.DecodeMethodSignature(new TypeReferenceSignatureDecoder(), default); method = new VarArgInstanceMethod( method, - methodReference.Parameters.SkipWhile(p => !p.ParameterType.IsSentinel).Select(p => Resolve(p.ParameterType)) + signature.ParameterTypes.Skip(signature.RequiredParameterCount).Select(p => p.Resolve(context)) ); - } else if (methodReference.IsGenericInstance || methodReference.DeclaringType.IsGenericInstance) { + break; + case SRM.HandleKind.MethodSpecification: IReadOnlyList classTypeArguments = null; IReadOnlyList methodTypeArguments = null; - if (methodReference.IsGenericInstance) { - var gim = ((GenericInstanceMethod)methodReference); - methodTypeArguments = gim.GenericArguments.SelectArray(Resolve); + var methodSpec = metadata.GetMethodSpecification((SRM.MethodSpecificationHandle)methodReference); + var typeArguments = methodSpec.DecodeSignature(new TypeReferenceSignatureDecoder(), default); + if (typeArguments.Length > 0) { + methodTypeArguments = typeArguments.SelectArray(arg => arg.Resolve(context)); } + var methodmethodSpec.Method.ResolveAsMethod(moduleDefinition); if (methodReference.DeclaringType.IsGenericInstance) { var git = (GenericInstanceType)methodReference.DeclaringType; classTypeArguments = git.GenericArguments.SelectArray(Resolve); } method = method.Specialize(new TypeParameterSubstitution(classTypeArguments, methodTypeArguments)); - } + break; + + }*/ methodLookupCache.Add(methodReference, method); } return method; } } - IMethod FindNonGenericMethod(MethodReference methodReference) + /*IMethod FindNonGenericMethod(SRM.MetadataReader metadata, Metadata.MethodDefinition method) { - ITypeDefinition typeDef = Resolve(methodReference.DeclaringType).GetDefinition(); + var methodDefinition = metadata.GetMethodDefinition(method.Handle); + ITypeDefinition typeDef = ResolveAsType(methodDefinition.GetDeclaringType()).GetDefinition(); if (typeDef == null) - return CreateFakeMethod(methodReference); + return CreateFakeMethod(methodDefinition); IEnumerable methods; - if (methodReference.Name == ".ctor") { + var name = metadata.GetString(methodDefinition.Name); + if (name == ".ctor") { methods = typeDef.GetConstructors(); - } else if (methodReference.Name == ".cctor") { + } else if (name == ".cctor") { return typeDef.Methods.FirstOrDefault(m => m.IsConstructor && m.IsStatic); } else { - methods = typeDef.GetMethods(m => m.Name == methodReference.Name, GetMemberOptions.IgnoreInheritedMembers) - .Concat(typeDef.GetAccessors(m => m.Name == methodReference.Name, GetMemberOptions.IgnoreInheritedMembers)); + methods = typeDef.GetMethods(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers) + .Concat(typeDef.GetAccessors(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers)); } - foreach (var method in methods) { - if (GetCecil(method) == methodReference) - return method; + foreach (var m in methods) { + if (GetMetadata(m).AsMethod() == method) + return m; } IType[] parameterTypes; - if (methodReference.CallingConvention == MethodCallingConvention.VarArg) { - parameterTypes = methodReference.Parameters - .TakeWhile(p => !p.ParameterType.IsSentinel) - .Select(p => Resolve(p.ParameterType)) + var signature = methodDefinition.DecodeSignature(new TypeReferenceSignatureDecoder(), default); + if (signature.Header.CallingConvention == SRM.SignatureCallingConvention.VarArgs) { + parameterTypes = signature.ParameterTypes + .Take(signature.RequiredParameterCount) + .Select(p => p.Resolve(context)) .Concat(new[] { SpecialType.ArgList }) .ToArray(); } else { - parameterTypes = methodReference.Parameters.SelectArray(p => Resolve(p.ParameterType)); + parameterTypes = signature.ParameterTypes.SelectArray(p => p.Resolve(context)); } - var returnType = Resolve(methodReference.ReturnType); - foreach (var method in methods) { - if (method.TypeParameters.Count != methodReference.GenericParameters.Count) + var returnType = signature.ReturnType.Resolve(context); + foreach (var m in methods) { + if (m.TypeParameters.Count != signature.GenericParameterCount) continue; - if (!CompareSignatures(method.Parameters, parameterTypes) || !CompareTypes(method.ReturnType, returnType)) + if (!CompareSignatures(m.Parameters, parameterTypes) || !CompareTypes(m.ReturnType, returnType)) continue; - return method; + return m; } - return CreateFakeMethod(methodReference); - } + return CreateFakeMethod(methodDefinition); + }*/ static bool CompareTypes(IType a, IType b) { @@ -318,29 +377,33 @@ namespace ICSharpCode.Decompiler.TypeSystem /// /// Create a dummy IMethod from the specified MethodReference /// - IMethod CreateFakeMethod(MethodReference methodReference) + IMethod CreateFakeMethod(IType declaringType, string name, SRM.MethodSignature signature) { - throw new NotImplementedException(); -#if false var m = new DefaultUnresolvedMethod(); - ITypeReference declaringTypeReference; + if (name == ".ctor" || name == ".cctor") + m.SymbolKind = SymbolKind.Constructor; + m.Name = name; + m.ReturnType = signature.ReturnType; + m.IsStatic = !signature.Header.IsInstance; + + /*ITypeReference declaringTypeReference; lock (typeReferenceCecilLoader) { - declaringTypeReference = typeReferenceCecilLoader.ReadTypeReference(methodReference.DeclaringType); - if (methodReference.Name == ".ctor" || methodReference.Name == ".cctor") - m.SymbolKind = SymbolKind.Constructor; - m.Name = methodReference.Name; - m.ReturnType = typeReferenceCecilLoader.ReadTypeReference(methodReference.ReturnType); - m.IsStatic = !methodReference.HasThis; - for (int i = 0; i < methodReference.GenericParameters.Count; i++) { - m.TypeParameters.Add(new DefaultUnresolvedTypeParameter(SymbolKind.Method, i, methodReference.GenericParameters[i].Name)); + var metadata = moduleDefinition.GetMetadataReader(); + declaringTypeReference = typeReferenceCecilLoader.ReadTypeReference(methodDefinition.GetDeclaringType()); + string name = metadata.GetString(methodDefinition.Name); + var gps = methodDefinition.GetGenericParameters(); + for (int i = 0; i < signature.GenericParameterCount; i++) { + var gp = metadata.GetGenericParameter(gps[i]); + m.TypeParameters.Add(new DefaultUnresolvedTypeParameter(SymbolKind.Method, i, metadata.GetString(gp.Name))); } - foreach (var p in methodReference.Parameters) { - m.Parameters.Add(new DefaultUnresolvedParameter(typeReferenceCecilLoader.ReadTypeReference(p.ParameterType), p.Name)); + var ps = methodDefinition.GetParameters(); + for (int i = 0; i < ps.Count; i++) { + var p = metadata.GetParameter(ps.At(metadata, i)); + m.Parameters.Add(new DefaultUnresolvedParameter(signature.ParameterTypes[i], metadata.GetString(p.Name))); } } - var type = declaringTypeReference.Resolve(context); - return new ResolvedFakeMethod(m, context.WithCurrentTypeDefinition(type.GetDefinition()), type); -#endif + var type = declaringTypeReference.Resolve(context);*/ + return new ResolvedFakeMethod(m, context.WithCurrentTypeDefinition(declaringType.GetDefinition()), declaringType); } class ResolvedFakeMethod : DefaultResolvedMethod @@ -360,76 +423,83 @@ namespace ICSharpCode.Decompiler.TypeSystem } #endregion -#region Resolve Property - public IProperty Resolve(PropertyReference propertyReference) + #region Resolve Property + public IProperty ResolveAsProperty(SRM.EntityHandle propertyReference) { - if (propertyReference == null) + if (propertyReference.IsNil) throw new ArgumentNullException(nameof(propertyReference)); + if (propertyReference.Kind != SRM.HandleKind.PropertyDefinition) + throw new ArgumentException("HandleKind must be PropertyDefinition", nameof(propertyReference)); lock (propertyLookupCache) { IProperty property; if (!propertyLookupCache.TryGetValue(propertyReference, out property)) { - property = FindNonGenericProperty(propertyReference); - if (propertyReference.DeclaringType.IsGenericInstance) { + var metadata = moduleDefinition.GetMetadataReader(); + property = FindNonGenericProperty(metadata, (SRM.PropertyDefinitionHandle)propertyReference); + /*if (propertyReference.DeclaringType.IsGenericInstance) { var git = (GenericInstanceType)propertyReference.DeclaringType; var typeArguments = git.GenericArguments.SelectArray(Resolve); property = (IProperty)property.Specialize(new TypeParameterSubstitution(typeArguments, null)); - } + }*/ propertyLookupCache.Add(propertyReference, property); } return property; } } - IProperty FindNonGenericProperty(PropertyReference propertyReference) + IProperty FindNonGenericProperty(SRM.MetadataReader metadata, SRM.PropertyDefinitionHandle handle) { - ITypeDefinition typeDef = Resolve(propertyReference.DeclaringType).GetDefinition(); + var propertyDefinition = metadata.GetPropertyDefinition(handle); + var declaringType = metadata.GetMethodDefinition(propertyDefinition.GetAccessors().GetAny()).GetDeclaringType(); + ITypeDefinition typeDef = ResolveAsType(declaringType).GetDefinition(); if (typeDef == null) return null; - var parameterTypes = propertyReference.Parameters.SelectArray(p => Resolve(p.ParameterType)); - var returnType = Resolve(propertyReference.PropertyType); foreach (IProperty property in typeDef.Properties) { - if (property.Name == propertyReference.Name - && CompareTypes(property.ReturnType, returnType) - && CompareSignatures(property.Parameters, parameterTypes)) + if (property.MetadataToken == handle) return property; } return null; } -#endregion + #endregion -#region Resolve Event - public IEvent Resolve(EventReference eventReference) + #region Resolve Event + public IEvent ResolveAsEvent(SRM.EntityHandle eventReference) { - if (eventReference == null) - throw new ArgumentNullException("propertyReference"); + if (eventReference.IsNil) + throw new ArgumentNullException(nameof(eventReference)); + if (eventReference.Kind != SRM.HandleKind.EventDefinition) + throw new ArgumentException("HandleKind must be EventDefinition", nameof(eventReference)); lock (eventLookupCache) { IEvent ev; if (!eventLookupCache.TryGetValue(eventReference, out ev)) { - ev = FindNonGenericEvent(eventReference); - if (eventReference.DeclaringType.IsGenericInstance) { + var metadata = moduleDefinition.GetMetadataReader(); + ev = FindNonGenericEvent(metadata, (SRM.EventDefinitionHandle)eventReference); + /*if (eventReference.DeclaringType.IsGenericInstance) { var git = (GenericInstanceType)eventReference.DeclaringType; var typeArguments = git.GenericArguments.SelectArray(Resolve); ev = (IEvent)ev.Specialize(new TypeParameterSubstitution(typeArguments, null)); - } + }*/ eventLookupCache.Add(eventReference, ev); } return ev; } } - IEvent FindNonGenericEvent(EventReference eventReference) + IEvent FindNonGenericEvent(SRM.MetadataReader metadata, SRM.EventDefinitionHandle handle) { - ITypeDefinition typeDef = Resolve(eventReference.DeclaringType).GetDefinition(); + var eventDefinition = metadata.GetEventDefinition(handle); + var declaringType = metadata.GetMethodDefinition(eventDefinition.GetAccessors().GetAny()).GetDeclaringType(); + ITypeDefinition typeDef = ResolveAsType(declaringType).GetDefinition(); if (typeDef == null) return null; - var returnType = Resolve(eventReference.EventType); + var returnType = ResolveAsType(eventDefinition.Type); + string name = metadata.GetString(eventDefinition.Name); foreach (IEvent ev in typeDef.Events) { - if (ev.Name == eventReference.Name && CompareTypes(ev.ReturnType, returnType)) + if (ev.MetadataToken == handle) return ev; } return null; } -#endregion + #endregion public IDecompilerTypeSystem GetSpecializingTypeSystem(TypeParameterSubstitution substitution) { diff --git a/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs index b0d5009fc..cb1415a48 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs @@ -16,7 +16,7 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. -using Mono.Cecil; +using System.Reflection.Metadata; namespace ICSharpCode.Decompiler.TypeSystem { @@ -27,12 +27,10 @@ namespace ICSharpCode.Decompiler.TypeSystem { ICompilation Compilation { get; } - TypeDefinition GetCecil(ITypeDefinition typeDefinition); - MemberReference GetCecil(IMember member); - - IType Resolve(TypeReference typeReference); - IField Resolve(FieldReference fieldReference); - IMethod Resolve(MethodReference methodReference); + IType ResolveAsType(EntityHandle typeReference); + IField ResolveAsField(EntityHandle fieldReference); + IMethod ResolveAsMethod(EntityHandle methodReference); + IMember ResolveAsMember(EntityHandle memberReference); /// /// Gets a type system instance that automatically specializes the results diff --git a/ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs b/ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs index 19ad8712b..70fc97b2f 100644 --- a/ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs +++ b/ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs @@ -92,18 +92,10 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Warning: if delay-loading is used and the type system is accessed by multiple threads, /// the callback may be invoked concurrently on multiple threads. /// - public Action OnEntityLoaded { get; set; } - - /// - /// Gets a value indicating whether this instance stores references to the cecil objects. - /// - /// - /// true if this instance has references to the cecil objects; otherwise, false. - /// - public bool HasCecilReferences { get { return typeSystemTranslationTable != null; } } - + public Action OnEntityLoaded { get; set; } + bool shortenInterfaceImplNames = true; - + /// /// Specifies whether method names of explicit interface-implementations should be shortened. /// @@ -118,30 +110,27 @@ namespace ICSharpCode.Decompiler.TypeSystem } #endregion - Metadata.PEFile currentModule; - MetadataReader currentModuleMetadata; + MetadataReader currentModule; DefaultUnresolvedAssembly currentAssembly; - + /// /// Initializes a new instance of the class. /// public MetadataLoader() { } - + /// /// Creates a nested CecilLoader for lazy-loading. /// private MetadataLoader(MetadataLoader loader) { // use a shared typeSystemTranslationTable - this.typeSystemTranslationTable = loader.typeSystemTranslationTable; this.IncludeInternalMembers = loader.IncludeInternalMembers; this.LazyLoad = loader.LazyLoad; this.OnEntityLoaded = loader.OnEntityLoaded; this.ShortenInterfaceImplNames = loader.ShortenInterfaceImplNames; this.currentModule = loader.currentModule; - this.currentModuleMetadata = loader.currentModuleMetadata; this.currentAssembly = loader.currentAssembly; // don't use interning - the interning provider is most likely not thread-safe this.interningProvider = InterningProvider.Dummy; @@ -153,31 +142,31 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Loads a module definition into a project content. /// /// Unresolved type system representing the assembly - public IUnresolvedAssembly LoadModule(Metadata.PEFile module) + public IUnresolvedAssembly LoadModule(MetadataReader module) { this.currentModule = module; - this.currentModuleMetadata = module.GetMetadataReader(); // Read assembly and module attributes IList assemblyAttributes = new List(); IList moduleAttributes = new List(); AssemblyDefinition assemblyDefinition = default(AssemblyDefinition); - if (currentModuleMetadata.IsAssembly) { - AddAttributes(currentModuleMetadata.GetAssemblyDefinition(), assemblyAttributes); + if (currentModule.IsAssembly) { + AddAttributes(currentModule.GetAssemblyDefinition(), assemblyAttributes); } AddAttributes(Handle.ModuleDefinition, moduleAttributes); assemblyAttributes = interningProvider.InternList(assemblyAttributes); moduleAttributes = interningProvider.InternList(moduleAttributes); - this.currentAssembly = new DefaultUnresolvedAssembly(currentModuleMetadata.IsAssembly ? currentModuleMetadata.GetFullAssemblyName() : currentModuleMetadata.GetString(currentModuleMetadata.GetModuleDefinition().Name)); + this.currentAssembly = new DefaultUnresolvedAssembly(currentModule.IsAssembly ? currentModule.GetFullAssemblyName() : currentModule.GetString(currentModule.GetModuleDefinition().Name)); currentAssembly.AssemblyAttributes.AddRange(assemblyAttributes); currentAssembly.ModuleAttributes.AddRange(assemblyAttributes); // Register type forwarders: - foreach (ExportedTypeHandle t in currentModuleMetadata.ExportedTypes) { - var type = currentModuleMetadata.GetExportedType(t); - if (type.IsForwarder) {/* + foreach (ExportedTypeHandle t in currentModule.ExportedTypes) { + var type = currentModule.GetExportedType(t); + if (type.IsForwarder) { + throw new NotImplementedException();/* switch (type.Implementation.Kind) { case HandleKind.AssemblyFile: throw new NotImplementedException(); // type is defined in another module. @@ -188,8 +177,8 @@ namespace ICSharpCode.Decompiler.TypeSystem break; } int typeParameterCount; - string ns = currentModuleMetadata.GetString(type.Namespace); - string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(currentModuleMetadata.GetString(type.Name), out typeParameterCount); + string ns = currentModule.GetString(type.Namespace); + string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(currentModule.GetString(type.Name), out typeParameterCount); ns = interningProvider.Intern(ns); name = interningProvider.Intern(name); @@ -204,18 +193,18 @@ namespace ICSharpCode.Decompiler.TypeSystem MetadataLoader cecilLoaderCloneForLazyLoading = LazyLoad ? new MetadataLoader(this) : null; List cecilTypeDefs = new List(); List typeDefs = new List(); - foreach (TypeDefinitionHandle h in currentModuleMetadata.TypeDefinitions) { + foreach (TypeDefinitionHandle h in module.TypeDefinitions) { this.CancellationToken.ThrowIfCancellationRequested(); - var td = currentModuleMetadata.GetTypeDefinition(h); + var td = module.GetTypeDefinition(h); if (this.IncludeInternalMembers || (td.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) { - string name = currentModuleMetadata.GetString(td.Name); + string name = module.GetString(td.Name); if (name.Length == 0) continue; if (this.LazyLoad) { - var t = new LazySRMTypeDefinition(cecilLoaderCloneForLazyLoading, new Metadata.TypeDefinition(currentModule, h)); + var t = new LazySRMTypeDefinition(cecilLoaderCloneForLazyLoading, module, h); currentAssembly.AddTypeDefinition(t); - RegisterCecilObject(t, new Metadata.TypeDefinition(currentModule, h)); + RegisterCecilObject(t, h); } else { var t = CreateTopLevelTypeDefinition(td); cecilTypeDefs.Add(h); @@ -244,21 +233,19 @@ namespace ICSharpCode.Decompiler.TypeSystem var result = this.currentAssembly; this.currentAssembly = null; this.currentModule = null; - this.currentModuleMetadata = null; return result; } - + /// /// Sets the current module. /// This causes ReadTypeReference() to use for references /// in that module. /// - public void SetCurrentModule(Metadata.PEFile module) + public void SetCurrentModule(MetadataReader module) { this.currentModule = module; - this.currentModuleMetadata = module.GetMetadataReader(); } - + /// /// Loads a type from Cecil. /// @@ -268,21 +255,22 @@ namespace ICSharpCode.Decompiler.TypeSystem { if (typeDefinition.IsNil) throw new ArgumentNullException(nameof(typeDefinition)); - var td = CreateTopLevelTypeDefinition(currentModuleMetadata.GetTypeDefinition(typeDefinition)); + var td = CreateTopLevelTypeDefinition(currentModule.GetTypeDefinition(typeDefinition)); InitTypeDefinition(typeDefinition, td); return td; } #endregion - + #region Load Assembly From Disk public IUnresolvedAssembly LoadAssemblyFile(string fileName) { if (fileName == null) throw new ArgumentNullException(nameof(fileName)); - return LoadModule(Metadata.UniversalAssemblyResolver.LoadMainModule(fileName)); + using (var module = new PEReader(new FileStream(fileName, FileMode.Open))) + return LoadModule(module.GetMetadataReader()); } #endregion - + #region Read Type Reference /// /// Reads a type reference. @@ -293,8 +281,26 @@ namespace ICSharpCode.Decompiler.TypeSystem /// This is used to support the 'dynamic' type. public ITypeReference ReadTypeReference(EntityHandle type, SRM.CustomAttributeHandleCollection typeAttributes = default(CustomAttributeHandleCollection)) { - int typeIndex = 0; - return CreateType(type, typeAttributes, ref typeIndex); + ITypeReference CreateTypeReference(TypeReferenceHandle handle) + { + var t = currentModule.GetTypeReference(handle); + var asmref = handle.GetDeclaringAssembly(currentModule); + if (asmref.IsNil) + return new GetClassTypeReference(handle.GetFullTypeName(currentModule), DefaultAssemblyReference.CurrentAssembly); + var asm = currentModule.GetAssemblyReference(asmref); + return new GetClassTypeReference(handle.GetFullTypeName(currentModule), new DefaultAssemblyReference(currentModule.GetString(asm.Name))); + } + + switch (type.Kind) { + case HandleKind.TypeSpecification: + return new SignatureTypeReference((TypeSpecificationHandle)type, currentModule); + case HandleKind.TypeReference: + return CreateTypeReference((TypeReferenceHandle)type); + case HandleKind.TypeDefinition: + return new TypeDefTokenTypeReference(type); + default: + throw new NotSupportedException(); + } } class DynamicTypeVisitor : TypeVisitor @@ -304,28 +310,24 @@ namespace ICSharpCode.Decompiler.TypeSystem return base.VisitPointerType(type); } } - - ITypeReference CreateType(EntityHandle type, CustomAttributeHandleCollection typeAttributes, ref int typeIndex) + + sealed class TypeDefTokenTypeReference : ITypeReference { - ITypeReference CreateTypeReference(TypeReferenceHandle handle) + readonly EntityHandle token; + + public TypeDefTokenTypeReference(EntityHandle token) { - var t = currentModuleMetadata.GetTypeReference(handle); - var asmref = handle.GetDeclaringAssembly(currentModuleMetadata); - if (asmref.IsNil) - return new GetClassTypeReference(handle.GetFullTypeName(currentModuleMetadata), DefaultAssemblyReference.CurrentAssembly); - var asm = currentModuleMetadata.GetAssemblyReference(asmref); - return new GetClassTypeReference(handle.GetFullTypeName(currentModuleMetadata), new DefaultAssemblyReference(currentModuleMetadata.GetString(asm.Name))); + if (token.Kind != HandleKind.TypeDefinition) + throw new ArgumentException(nameof(token), "must be TypeDef token"); + this.token = token; } - switch (type.Kind) { - case HandleKind.TypeSpecification: - return new SignatureTypeReference((TypeSpecificationHandle)type, currentModuleMetadata); - case HandleKind.TypeReference: - return CreateTypeReference((TypeReferenceHandle)type); - case HandleKind.TypeDefinition: - return new DefaultUnresolvedTypeDefinition(type.GetFullTypeName(currentModuleMetadata).ReflectionName); - default: - throw new NotSupportedException(); + public IType Resolve(ITypeResolveContext context) + { + ITypeDefinition td = context.CurrentAssembly.ResolveTypeDefToken(token); + if (td != null) + return td; + return SpecialType.UnknownType; } } #endregion @@ -333,12 +335,12 @@ namespace ICSharpCode.Decompiler.TypeSystem #region Read Attributes #region Assembly Attributes static readonly ITypeReference assemblyVersionAttributeTypeRef = typeof(System.Reflection.AssemblyVersionAttribute).ToTypeReference(); - + void AddAttributes(AssemblyDefinition assembly, IList outputList) { - AddCustomAttributes(currentModuleMetadata.GetCustomAttributes((EntityHandle)Handle.AssemblyDefinition), outputList); + AddCustomAttributes(currentModule.GetCustomAttributes((EntityHandle)Handle.AssemblyDefinition), outputList); AddSecurityAttributes(assembly.GetDeclarativeSecurityAttributes(), outputList); - + // AssemblyVersionAttribute if (assembly.Version != null) { var assemblyVersion = new DefaultUnresolvedAttribute(assemblyVersionAttributeTypeRef, new[] { KnownTypeReference.String }); @@ -346,24 +348,24 @@ namespace ICSharpCode.Decompiler.TypeSystem outputList.Add(interningProvider.Intern(assemblyVersion)); } } - + IConstantValue CreateSimpleConstantValue(ITypeReference type, object value) { return interningProvider.Intern(new SimpleConstantValue(type, interningProvider.InternValue(value))); } #endregion - + #region Module Attributes void AddAttributes(ModuleDefinitionHandle module, IList outputList) { - AddCustomAttributes(currentModuleMetadata.GetCustomAttributes(module), outputList); + AddCustomAttributes(currentModule.GetCustomAttributes(module), outputList); } #endregion - + #region Parameter Attributes static readonly IUnresolvedAttribute inAttribute = new DefaultUnresolvedAttribute(typeof(InAttribute).ToTypeReference()); static readonly IUnresolvedAttribute outAttribute = new DefaultUnresolvedAttribute(typeof(OutAttribute).ToTypeReference()); - + void AddAttributes(Parameter parameter, DefaultUnresolvedParameter targetParameter) { if (!targetParameter.IsOut) { @@ -376,7 +378,7 @@ namespace ICSharpCode.Decompiler.TypeSystem AddMarshalInfo(parameter.GetMarshallingDescriptor(), targetParameter.Attributes); } #endregion - + #region Method Attributes static readonly ITypeReference dllImportAttributeTypeRef = typeof(DllImportAttribute).ToTypeReference(); static readonly SimpleConstantValue trueValue = new SimpleConstantValue(KnownTypeReference.Boolean, true); @@ -385,7 +387,7 @@ namespace ICSharpCode.Decompiler.TypeSystem static readonly IUnresolvedAttribute preserveSigAttribute = new DefaultUnresolvedAttribute(typeof(PreserveSigAttribute).ToTypeReference()); static readonly ITypeReference methodImplAttributeTypeRef = typeof(MethodImplAttribute).ToTypeReference(); static readonly ITypeReference methodImplOptionsTypeRef = typeof(MethodImplOptions).ToTypeReference(); - + bool HasAnyAttributes(MethodDefinition methodDefinition) { if ((methodDefinition.Attributes & MethodAttributes.PinvokeImpl) == MethodAttributes.PinvokeImpl) @@ -393,7 +395,7 @@ namespace ICSharpCode.Decompiler.TypeSystem if ((methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask) != 0) return true; if (methodDefinition.GetParameters().Count > 0) { - var retParam = currentModuleMetadata.GetParameter(methodDefinition.GetParameters().First()); + var retParam = currentModule.GetParameter(methodDefinition.GetParameters().First()); if (retParam.GetCustomAttributes().Count > 0) return true; @@ -402,7 +404,7 @@ namespace ICSharpCode.Decompiler.TypeSystem } return methodDefinition.GetCustomAttributes().Count > 0; } - + void AddAttributes(MethodDefinition methodDefinition, IList attributes, IList returnTypeAttributes) { MethodImplAttributes implAttributes = methodDefinition.ImplAttributes & ~MethodImplAttributes.CodeTypeMask; @@ -411,17 +413,17 @@ namespace ICSharpCode.Decompiler.TypeSystem var info = methodDefinition.GetImport(); if ((methodDefinition.Attributes & MethodAttributes.PinvokeImpl) == MethodAttributes.PinvokeImpl && !info.Module.IsNil) { var dllImport = new DefaultUnresolvedAttribute(dllImportAttributeTypeRef, new[] { KnownTypeReference.String }); - dllImport.PositionalArguments.Add(CreateSimpleConstantValue(KnownTypeReference.String, currentModuleMetadata.GetString(currentModuleMetadata.GetModuleReference(info.Module).Name))); - + dllImport.PositionalArguments.Add(CreateSimpleConstantValue(KnownTypeReference.String, currentModule.GetString(currentModule.GetModuleReference(info.Module).Name))); + if ((info.Attributes & MethodImportAttributes.BestFitMappingDisable) == MethodImportAttributes.BestFitMappingDisable) dllImport.AddNamedFieldArgument("BestFitMapping", falseValue); if ((info.Attributes & MethodImportAttributes.BestFitMappingEnable) == MethodImportAttributes.BestFitMappingEnable) dllImport.AddNamedFieldArgument("BestFitMapping", trueValue); - + CallingConvention callingConvention; switch (info.Attributes & MethodImportAttributes.CallingConventionMask) { case 0: - Debug.WriteLine ($"P/Invoke calling convention not set on: {methodDefinition.GetDeclaringType().GetFullTypeName(currentModuleMetadata).ToString()}.{currentModuleMetadata.GetString(methodDefinition.Name)}"); + Debug.WriteLine($"P/Invoke calling convention not set on: {methodDefinition.GetDeclaringType().GetFullTypeName(currentModule).ToString()}.{currentModule.GetString(methodDefinition.Name)}"); callingConvention = 0; break; case MethodImportAttributes.CallingConventionCDecl: @@ -444,7 +446,7 @@ namespace ICSharpCode.Decompiler.TypeSystem } if (callingConvention != CallingConvention.Winapi) dllImport.AddNamedFieldArgument("CallingConvention", CreateSimpleConstantValue(callingConventionTypeRef, (int)callingConvention)); - + CharSet charSet = CharSet.None; switch (info.Attributes & MethodImportAttributes.CharSetMask) { case MethodImportAttributes.CharSetAnsi: @@ -459,37 +461,37 @@ namespace ICSharpCode.Decompiler.TypeSystem } if (charSet != CharSet.None) dllImport.AddNamedFieldArgument("CharSet", CreateSimpleConstantValue(charSetTypeRef, (int)charSet)); - + if (!info.Name.IsNil && info.Name != methodDefinition.Name) - dllImport.AddNamedFieldArgument("EntryPoint", CreateSimpleConstantValue(KnownTypeReference.String, currentModuleMetadata.GetString(info.Name))); - + dllImport.AddNamedFieldArgument("EntryPoint", CreateSimpleConstantValue(KnownTypeReference.String, currentModule.GetString(info.Name))); + if ((info.Attributes & MethodImportAttributes.ExactSpelling) == MethodImportAttributes.ExactSpelling) dllImport.AddNamedFieldArgument("ExactSpelling", trueValue); - + if ((implAttributes & MethodImplAttributes.PreserveSig) == MethodImplAttributes.PreserveSig) implAttributes &= ~MethodImplAttributes.PreserveSig; else dllImport.AddNamedFieldArgument("PreserveSig", falseValue); - + if ((info.Attributes & MethodImportAttributes.SetLastError) == MethodImportAttributes.SetLastError) dllImport.AddNamedFieldArgument("SetLastError", trueValue); - + if ((info.Attributes & MethodImportAttributes.ThrowOnUnmappableCharDisable) == MethodImportAttributes.ThrowOnUnmappableCharDisable) dllImport.AddNamedFieldArgument("ThrowOnUnmappableChar", falseValue); if ((info.Attributes & MethodImportAttributes.ThrowOnUnmappableCharEnable) == MethodImportAttributes.ThrowOnUnmappableCharEnable) dllImport.AddNamedFieldArgument("ThrowOnUnmappableChar", trueValue); - + attributes.Add(interningProvider.Intern(dllImport)); } #endregion - + #region PreserveSigAttribute if (implAttributes == MethodImplAttributes.PreserveSig) { attributes.Add(preserveSigAttribute); implAttributes = 0; } #endregion - + #region MethodImplAttribute if (implAttributes != 0) { var methodImpl = new DefaultUnresolvedAttribute(methodImplAttributeTypeRef, new[] { methodImplOptionsTypeRef }); @@ -497,39 +499,39 @@ namespace ICSharpCode.Decompiler.TypeSystem attributes.Add(interningProvider.Intern(methodImpl)); } #endregion - + AddCustomAttributes(methodDefinition.GetCustomAttributes(), attributes); AddSecurityAttributes(methodDefinition.GetDeclarativeSecurityAttributes(), attributes); if (methodDefinition.GetParameters().Count > 0) { - var retParam = currentModuleMetadata.GetParameter(methodDefinition.GetParameters().First()); + var retParam = currentModule.GetParameter(methodDefinition.GetParameters().First()); var marshallingDesc = retParam.GetMarshallingDescriptor(); if (!marshallingDesc.IsNil) { - returnTypeAttributes.Add(ConvertMarshalInfo(currentModuleMetadata.GetBlobReader(marshallingDesc))); + returnTypeAttributes.Add(ConvertMarshalInfo(currentModule.GetBlobReader(marshallingDesc))); } AddCustomAttributes(retParam.GetCustomAttributes(), returnTypeAttributes); } } #endregion - + #region Type Attributes static readonly DefaultUnresolvedAttribute serializableAttribute = new DefaultUnresolvedAttribute(typeof(SerializableAttribute).ToTypeReference()); static readonly DefaultUnresolvedAttribute comImportAttribute = new DefaultUnresolvedAttribute(typeof(ComImportAttribute).ToTypeReference()); static readonly ITypeReference structLayoutAttributeTypeRef = typeof(StructLayoutAttribute).ToTypeReference(); static readonly ITypeReference layoutKindTypeRef = typeof(LayoutKind).ToTypeReference(); static readonly ITypeReference charSetTypeRef = typeof(CharSet).ToTypeReference(); - + void AddAttributes(TypeDefinition typeDefinition, IUnresolvedTypeDefinition targetEntity) { // SerializableAttribute if ((typeDefinition.Attributes & TypeAttributes.Serializable) != 0) targetEntity.Attributes.Add(serializableAttribute); - + // ComImportAttribute if ((typeDefinition.Attributes & TypeAttributes.Import) != 0) targetEntity.Attributes.Add(comImportAttribute); - + #region StructLayoutAttribute LayoutKind layoutKind = LayoutKind.Auto; switch (typeDefinition.Attributes & TypeAttributes.LayoutMask) { @@ -553,7 +555,7 @@ namespace ICSharpCode.Decompiler.TypeSystem break; } var layout = typeDefinition.GetLayout(); - LayoutKind defaultLayoutKind = (typeDefinition.IsValueType(currentModuleMetadata) && !typeDefinition.IsEnum(currentModuleMetadata)) ? LayoutKind.Sequential : LayoutKind.Auto; + LayoutKind defaultLayoutKind = (typeDefinition.IsValueType(currentModule) && !typeDefinition.IsEnum(currentModule)) ? LayoutKind.Sequential : LayoutKind.Auto; if (layoutKind != defaultLayoutKind || charSet != CharSet.Ansi || layout.PackingSize > 0 || layout.Size > 0) { DefaultUnresolvedAttribute structLayout = new DefaultUnresolvedAttribute(structLayoutAttributeTypeRef, new[] { layoutKindTypeRef }); structLayout.PositionalArguments.Add(CreateSimpleConstantValue(layoutKindTypeRef, (int)layoutKind)); @@ -569,16 +571,16 @@ namespace ICSharpCode.Decompiler.TypeSystem targetEntity.Attributes.Add(interningProvider.Intern(structLayout)); } #endregion - + AddCustomAttributes(typeDefinition.GetCustomAttributes(), targetEntity.Attributes); AddSecurityAttributes(typeDefinition.GetDeclarativeSecurityAttributes(), targetEntity.Attributes); } #endregion - + #region Field Attributes static readonly ITypeReference fieldOffsetAttributeTypeRef = typeof(FieldOffsetAttribute).ToTypeReference(); static readonly IUnresolvedAttribute nonSerializedAttribute = new DefaultUnresolvedAttribute(typeof(NonSerializedAttribute).ToTypeReference()); - + void AddAttributes(FieldDefinition fieldDefinition, IUnresolvedEntity targetEntity) { // FieldOffsetAttribute @@ -588,37 +590,37 @@ namespace ICSharpCode.Decompiler.TypeSystem fieldOffset.PositionalArguments.Add(CreateSimpleConstantValue(KnownTypeReference.Int32, offset)); targetEntity.Attributes.Add(interningProvider.Intern(fieldOffset)); } - + // NonSerializedAttribute if ((fieldDefinition.Attributes & FieldAttributes.NotSerialized) != 0) { targetEntity.Attributes.Add(nonSerializedAttribute); } - AddMarshalInfo(fieldDefinition.GetMarshallingDescriptor(), targetEntity.Attributes); + AddMarshalInfo(fieldDefinition.GetMarshallingDescriptor(), targetEntity.Attributes); AddCustomAttributes(fieldDefinition.GetCustomAttributes(), targetEntity.Attributes); } #endregion - + #region Event Attributes void AddAttributes(EventDefinition eventDefinition, IUnresolvedEntity targetEntity) { AddCustomAttributes(eventDefinition.GetCustomAttributes(), targetEntity.Attributes); } #endregion - + #region Property Attributes void AddAttributes(PropertyDefinition propertyDefinition, IUnresolvedEntity targetEntity) { AddCustomAttributes(propertyDefinition.GetCustomAttributes(), targetEntity.Attributes); } #endregion - + #region Type Parameter Attributes void AddAttributes(GenericParameter genericParameter, IUnresolvedTypeParameter targetTP) { AddCustomAttributes(genericParameter.GetCustomAttributes(), targetTP.Attributes); } #endregion - + #region MarshalAsAttribute (ConvertMarshalInfo) static readonly ITypeReference marshalAsAttributeTypeRef = typeof(MarshalAsAttribute).ToTypeReference(); static readonly ITypeReference unmanagedTypeTypeRef = typeof(UnmanagedType).ToTypeReference(); @@ -628,7 +630,7 @@ namespace ICSharpCode.Decompiler.TypeSystem if (marshalInfo.IsNil) return; } - + IUnresolvedAttribute ConvertMarshalInfo(System.Reflection.Metadata.BlobReader marshalInfo) { int type = marshalInfo.ReadByte(); @@ -679,18 +681,18 @@ namespace ICSharpCode.Decompiler.TypeSystem attr.AddNamedFieldArgument("SizeConst", CreateSimpleConstantValue(KnownTypeReference.Int32, marshalInfo.ReadCompressedInteger())); break; } - + return InterningProvider.Intern(attr); } #endregion - + #region Custom Attributes (ReadAttribute) void AddCustomAttributes(CustomAttributeHandleCollection attributes, IList targetCollection) { foreach (var handle in attributes) { - var attribute = currentModuleMetadata.GetCustomAttribute(handle); - var typeHandle = attribute.GetAttributeType(currentModuleMetadata); - switch (typeHandle.GetFullTypeName(currentModuleMetadata).ReflectionName) { + var attribute = currentModule.GetCustomAttribute(handle); + var typeHandle = attribute.GetAttributeType(currentModule); + switch (typeHandle.GetFullTypeName(currentModule).ReflectionName) { case "System.Runtime.CompilerServices.DynamicAttribute": case "System.Runtime.CompilerServices.ExtensionAttribute": case "System.Runtime.CompilerServices.DecimalConstantAttribute": @@ -700,14 +702,14 @@ namespace ICSharpCode.Decompiler.TypeSystem targetCollection.Add(ReadAttribute(attribute)); } } - + public IUnresolvedAttribute ReadAttribute(CustomAttribute attribute) { - ITypeReference attributeType = ReadTypeReference(attribute.GetAttributeType(currentModuleMetadata)); - return interningProvider.Intern(new MetadataUnresolvedAttributeBlob(currentModuleMetadata, attributeType, attribute)); + ITypeReference attributeType = ReadTypeReference(attribute.GetAttributeType(currentModule)); + return interningProvider.Intern(new MetadataUnresolvedAttributeBlob(currentModule, attributeType, attribute)); } #endregion - + #region Security Attributes /// /// Reads a security declaration. @@ -718,87 +720,88 @@ namespace ICSharpCode.Decompiler.TypeSystem AddSecurityAttributes(secDecl, result); return result; } - + void AddSecurityAttributes(DeclarativeSecurityAttributeHandleCollection securityDeclarations, IList targetCollection) { foreach (var secDecl in securityDeclarations) { if (secDecl.IsNil) continue; - AddSecurityAttributes(currentModuleMetadata.GetDeclarativeSecurityAttribute(secDecl), targetCollection); + AddSecurityAttributes(currentModule.GetDeclarativeSecurityAttribute(secDecl), targetCollection); } } - + void AddSecurityAttributes(DeclarativeSecurityAttribute secDecl, IList targetCollection) { - var blob = currentModuleMetadata.GetBlobBytes(secDecl.PermissionSet); + var blob = currentModule.GetBlobBytes(secDecl.PermissionSet); var blobSecDecl = new UnresolvedSecurityDeclarationBlob((int)secDecl.Action, blob); targetCollection.AddRange(blobSecDecl.UnresolvedAttributes); } #endregion #endregion - + #region Read Type Definition DefaultUnresolvedTypeDefinition CreateTopLevelTypeDefinition(TypeDefinition typeDefinition) { - string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(currentModuleMetadata.GetString(typeDefinition.Name)); - var td = new DefaultUnresolvedTypeDefinition(currentModuleMetadata.GetString(typeDefinition.Namespace), name); - InitTypeParameters(currentModuleMetadata, typeDefinition, td.TypeParameters); + string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(currentModule.GetString(typeDefinition.Name)); + var td = new DefaultUnresolvedTypeDefinition(currentModule.GetString(typeDefinition.Namespace), name); + //td.MetadataToken = ... + InitTypeParameters(currentModule, typeDefinition, td.TypeParameters); return td; } - - static void InitTypeParameters(MetadataReader currentModuleMetadata, TypeDefinition typeDefinition, IList typeParameters) + + static void InitTypeParameters(MetadataReader currentModule, TypeDefinition typeDefinition, IList typeParameters) { // Type parameters are initialized within the constructor so that the class can be put into the type storage // before the rest of the initialization runs - this allows it to be available for early binding as soon as possible. var genericParams = typeDefinition.GetGenericParameters(); for (int i = 0; i < genericParams.Count; i++) { - var gp = currentModuleMetadata.GetGenericParameter(genericParams[i]); + var gp = currentModule.GetGenericParameter(genericParams[i]); if (gp.Index != i) throw new InvalidOperationException("g.Position != i"); typeParameters.Add(new DefaultUnresolvedTypeParameter( - SymbolKind.TypeDefinition, i, currentModuleMetadata.GetString(gp.Name))); + SymbolKind.TypeDefinition, i, currentModule.GetString(gp.Name))); } } - + void InitTypeParameterConstraints(TypeDefinition typeDefinition, IList typeParameters) { var genericParams = typeDefinition.GetGenericParameters().ToArray(); for (int i = 0; i < typeParameters.Count; i++) { var tp = (DefaultUnresolvedTypeParameter)typeParameters[i]; - var gp = currentModuleMetadata.GetGenericParameter(genericParams[i]); + var gp = currentModule.GetGenericParameter(genericParams[i]); AddConstraints(tp, gp); AddAttributes(gp, tp); tp.ApplyInterningProvider(interningProvider); } } - + void InitTypeDefinition(TypeDefinitionHandle handle, DefaultUnresolvedTypeDefinition td) { - var typeDefinition = currentModuleMetadata.GetTypeDefinition(handle); - td.Kind = GetTypeKind(currentModuleMetadata, typeDefinition); + var typeDefinition = currentModule.GetTypeDefinition(handle); + td.Kind = GetTypeKind(currentModule, typeDefinition); InitTypeModifiers(typeDefinition, td); InitTypeParameterConstraints(typeDefinition, td.TypeParameters); - + // nested types can be initialized only after generic parameters were created InitNestedTypes(handle, td, td.NestedTypes); AddAttributes(typeDefinition, td); - td.HasExtensionMethods = HasExtensionAttribute(currentModuleMetadata, typeDefinition.GetCustomAttributes()); - + td.HasExtensionMethods = HasExtensionAttribute(currentModule, typeDefinition.GetCustomAttributes()); + InitBaseTypes(handle, td.BaseTypes); - + td.AddDefaultConstructorIfRequired = (td.Kind == TypeKind.Struct || td.Kind == TypeKind.Enum); InitMembers(typeDefinition, td, td.Members); td.ApplyInterningProvider(interningProvider); td.Freeze(); - RegisterCecilObject(td, new Metadata.TypeDefinition(currentModule, handle)); + RegisterCecilObject(td, handle); } - + void InitBaseTypes(TypeDefinitionHandle handle, IList baseTypes) { - var typeDefinition = currentModuleMetadata.GetTypeDefinition(handle); + var typeDefinition = currentModule.GetTypeDefinition(handle); // set base classes - if (typeDefinition.IsEnum(currentModuleMetadata)) { + if (typeDefinition.IsEnum(currentModule)) { foreach (FieldDefinitionHandle h in typeDefinition.GetFields()) { - var enumField = currentModuleMetadata.GetFieldDefinition(h); + var enumField = currentModule.GetFieldDefinition(h); if ((enumField.Attributes & FieldAttributes.Static) == 0) { baseTypes.Add(enumField.DecodeSignature(new TypeReferenceSignatureDecoder(), default(Unit))); break; @@ -809,36 +812,36 @@ namespace ICSharpCode.Decompiler.TypeSystem baseTypes.Add(ReadTypeReference(typeDefinition.BaseType)); } foreach (var h in typeDefinition.GetInterfaceImplementations()) { - var iface = currentModuleMetadata.GetInterfaceImplementation(h); + var iface = currentModule.GetInterfaceImplementation(h); baseTypes.Add(ReadTypeReference(iface.Interface, iface.GetCustomAttributes())); } } } - + void InitNestedTypes(TypeDefinitionHandle typeDefinitionHandle, IUnresolvedTypeDefinition declaringTypeDefinition, IList nestedTypes) { - var typeDefinition = currentModuleMetadata.GetTypeDefinition(typeDefinitionHandle); + var typeDefinition = currentModule.GetTypeDefinition(typeDefinitionHandle); foreach (TypeDefinitionHandle h in typeDefinition.GetNestedTypes()) { - var nestedTypeDef = currentModuleMetadata.GetTypeDefinition(h); + var nestedTypeDef = currentModule.GetTypeDefinition(h); TypeAttributes visibility = nestedTypeDef.Attributes & TypeAttributes.VisibilityMask; if (this.IncludeInternalMembers || visibility == TypeAttributes.NestedPublic || visibility == TypeAttributes.NestedFamily - || visibility == TypeAttributes.NestedFamORAssem) - { - string name = currentModuleMetadata.GetString(nestedTypeDef.Name); + || visibility == TypeAttributes.NestedFamORAssem) { + string name = currentModule.GetString(nestedTypeDef.Name); int pos = name.LastIndexOf('/'); if (pos > 0) name = name.Substring(pos + 1); name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name); var nestedType = new DefaultUnresolvedTypeDefinition(declaringTypeDefinition, name); - InitTypeParameters(currentModuleMetadata, nestedTypeDef, nestedType.TypeParameters); + nestedType.MetadataToken = h; + InitTypeParameters(currentModule, nestedTypeDef, nestedType.TypeParameters); nestedTypes.Add(nestedType); InitTypeDefinition(h, nestedType); } } } - + static TypeKind GetTypeKind(MetadataReader module, TypeDefinition typeDefinition) { // set classtype @@ -856,7 +859,7 @@ namespace ICSharpCode.Decompiler.TypeSystem return TypeKind.Class; } } - + static void InitTypeModifiers(TypeDefinition typeDefinition, AbstractUnresolvedEntity td) { td.IsSealed = (typeDefinition.Attributes & TypeAttributes.Sealed) == TypeAttributes.Sealed; @@ -884,67 +887,66 @@ namespace ICSharpCode.Decompiler.TypeSystem break; } } - - static bool IsDelegate(MetadataReader currentModuleMetadata, TypeDefinition type) + + static bool IsDelegate(MetadataReader currentModule, TypeDefinition type) { if (type.BaseType != null) { - var baseTypeName = type.BaseType.GetFullTypeName(currentModuleMetadata).ToString(); + var baseTypeName = type.BaseType.GetFullTypeName(currentModule).ToString(); if (baseTypeName == "System.MulticastDelegate") return true; - var thisTypeName = type.GetFullTypeName(currentModuleMetadata).ToString(); + var thisTypeName = type.GetFullTypeName(currentModule).ToString(); if (baseTypeName == "Delegate" && thisTypeName != "System.MulticastDelegate") return true; } return false; } - + static bool IsModule(MetadataReader reader, TypeDefinition type) { foreach (var h in type.GetCustomAttributes()) { var attType = reader.GetCustomAttribute(h).GetAttributeType(reader).GetFullTypeName(reader); if (attType.ToString() == "Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute" - || attType.ToString() == "System.Runtime.CompilerServices.CompilerGlobalScopeAttribute") - { + || attType.ToString() == "System.Runtime.CompilerServices.CompilerGlobalScopeAttribute") { return true; } } return false; } - + void InitMembers(TypeDefinition typeDefinition, IUnresolvedTypeDefinition td, IList members) { foreach (MethodDefinitionHandle h in typeDefinition.GetMethods()) { - var method = currentModuleMetadata.GetMethodDefinition(h); - /*if (IsVisible(method.Attributes) && !IsAccessor(h.GetMethodSemanticsAttributes(currentModuleMetadata))) { + var method = currentModule.GetMethodDefinition(h); + /*if (IsVisible(method.Attributes) && !IsAccessor(h.GetMethodSemanticsAttributes(currentModule))) { SymbolKind type = SymbolKind.Method; if ((method.Attributes & MethodAttributes.SpecialName) != 0) { - if (method.IsConstructor(currentModuleMetadata)) + if (method.IsConstructor(currentModule)) type = SymbolKind.Constructor; - else if (currentModuleMetadata.GetString(method.Name).StartsWith("op_", StringComparison.Ordinal)) + else if (currentModule.GetString(method.Name).StartsWith("op_", StringComparison.Ordinal)) type = SymbolKind.Operator; } members.Add(ReadMethod(h, td, type)); }*/ } foreach (FieldDefinitionHandle h in typeDefinition.GetFields()) { - var field = currentModuleMetadata.GetFieldDefinition(h); + var field = currentModule.GetFieldDefinition(h); if (IsVisible(field.Attributes) && (field.Attributes & FieldAttributes.SpecialName) != 0) { members.Add(ReadField(h, td)); } } - string defaultMemberName = GetDefaultMemberName(currentModuleMetadata, typeDefinition); + string defaultMemberName = GetDefaultMemberName(currentModule, typeDefinition); foreach (PropertyDefinitionHandle handle in typeDefinition.GetProperties()) { - var property = currentModuleMetadata.GetPropertyDefinition(handle); - bool getterVisible = !property.GetAccessors().Getter.IsNil && IsVisible(currentModuleMetadata.GetMethodDefinition(property.GetAccessors().Getter).Attributes); - bool setterVisible = !property.GetAccessors().Setter.IsNil && IsVisible(currentModuleMetadata.GetMethodDefinition(property.GetAccessors().Setter).Attributes); + var property = currentModule.GetPropertyDefinition(handle); + bool getterVisible = !property.GetAccessors().Getter.IsNil && IsVisible(currentModule.GetMethodDefinition(property.GetAccessors().Getter).Attributes); + bool setterVisible = !property.GetAccessors().Setter.IsNil && IsVisible(currentModule.GetMethodDefinition(property.GetAccessors().Setter).Attributes); if (getterVisible || setterVisible) { var accessor = property.GetAccessors().Getter.IsNil ? property.GetAccessors().Setter : property.GetAccessors().Getter; SymbolKind type = SymbolKind.Property; - if (handle.HasParameters(currentModuleMetadata)) { + if (handle.HasParameters(currentModule)) { // Try to detect indexer: - if (currentModuleMetadata.GetString(property.Name) == defaultMemberName) { + if (currentModule.GetString(property.Name) == defaultMemberName) { type = SymbolKind.Indexer; // normal indexer - } else if (currentModuleMetadata.GetString(property.Name).EndsWith(".Item", StringComparison.Ordinal) && accessor.HasOverrides(currentModuleMetadata)) { + } else if (currentModule.GetString(property.Name).EndsWith(".Item", StringComparison.Ordinal) && accessor.HasOverrides(currentModule)) { // explicit interface implementation of indexer type = SymbolKind.Indexer; // We can't really tell parameterized properties and indexers apart in this case without @@ -955,9 +957,9 @@ namespace ICSharpCode.Decompiler.TypeSystem } } foreach (EventDefinitionHandle h in typeDefinition.GetEvents()) { - var ev = currentModuleMetadata.GetEventDefinition(h); + var ev = currentModule.GetEventDefinition(h); if (ev.GetAccessors().Adder.IsNil) continue; - var addMethod = currentModuleMetadata.GetMethodDefinition(ev.GetAccessors().Adder); + var addMethod = currentModule.GetMethodDefinition(ev.GetAccessors().Adder); if (IsVisible(addMethod.Attributes)) { members.Add(ReadEvent(h, td)); } @@ -983,72 +985,69 @@ namespace ICSharpCode.Decompiler.TypeSystem return semantics != MethodSemanticsAttributes.Other; } #endregion - + #region Lazy-Loaded Type Definition sealed class LazySRMTypeDefinition : AbstractUnresolvedEntity, IUnresolvedTypeDefinition { // loader + cecilTypeDef, used for lazy-loading; and set to null after lazy loading is complete readonly MetadataLoader loader; - readonly Metadata.TypeDefinition typeDefinition; - + readonly MetadataReader module; + readonly string namespaceName; readonly TypeKind kind; readonly IList typeParameters; - + // lazy-loaded fields IList baseTypes; IList nestedTypes; IList members; - - public LazySRMTypeDefinition(MetadataLoader loader, Metadata.TypeDefinition typeDefinition) + + public LazySRMTypeDefinition(MetadataLoader loader, MetadataReader module, TypeDefinitionHandle typeDefinition) { this.loader = loader; - this.typeDefinition = typeDefinition; + this.MetadataToken = typeDefinition; this.SymbolKind = SymbolKind.TypeDefinition; - var metadata = typeDefinition.Module.GetMetadataReader(); - var td = typeDefinition.This(); - this.namespaceName = metadata.GetString(td.Namespace); - this.Name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(metadata.GetString(td.Name)); + var td = module.GetTypeDefinition(typeDefinition); + this.namespaceName = module.GetString(td.Namespace); + this.Name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(module.GetString(td.Name)); var tps = new List(); - InitTypeParameters(metadata, td, tps); + InitTypeParameters(module, td, tps); this.typeParameters = FreezableHelper.FreezeList(tps); - - this.kind = GetTypeKind(metadata, td); + + this.kind = GetTypeKind(module, td); InitTypeModifiers(td, this); loader.InitTypeParameterConstraints(td, typeParameters); - + loader.AddAttributes(td, this); - flags[FlagHasExtensionMethods] = HasExtensionAttribute(metadata, td.GetCustomAttributes()); - + flags[FlagHasExtensionMethods] = HasExtensionAttribute(module, td.GetCustomAttributes()); + this.ApplyInterningProvider(loader.interningProvider); this.Freeze(); } - + public override string Namespace { get { return namespaceName; } set { throw new NotSupportedException(); } } - + public override string ReflectionName { get { return this.FullTypeName.ReflectionName; } } - + public FullTypeName FullTypeName { get { return new TopLevelTypeName(namespaceName, this.Name, typeParameters.Count); } } - + public TypeKind Kind { get { return kind; } } - + public IList TypeParameters { get { return typeParameters; } } - public Metadata.IMetadataEntity MetadataToken => typeDefinition; - public IList BaseTypes { get { var result = LazyInit.VolatileRead(ref this.baseTypes); @@ -1059,16 +1058,16 @@ namespace ICSharpCode.Decompiler.TypeSystem } } } - + IList TryInitBaseTypes() { - lock (loader.currentModuleMetadata) { + lock (loader.currentModule) { var result = new List(); - loader.InitBaseTypes(typeDefinition.Handle, result); + loader.InitBaseTypes((TypeDefinitionHandle)MetadataToken, result); return FreezableHelper.FreezeList(result); } } - + public IList NestedTypes { get { var result = LazyInit.VolatileRead(ref this.nestedTypes); @@ -1079,16 +1078,16 @@ namespace ICSharpCode.Decompiler.TypeSystem } } } - + IList TryInitNestedTypes() { - lock (loader.currentModuleMetadata) { + lock (loader.currentModule) { var result = new List(); - loader.InitNestedTypes(typeDefinition.Handle, this, result); + loader.InitNestedTypes((TypeDefinitionHandle)MetadataToken, this, result); return FreezableHelper.FreezeList(result); } } - + public IList Members { get { var result = LazyInit.VolatileRead(ref this.members); @@ -1099,14 +1098,14 @@ namespace ICSharpCode.Decompiler.TypeSystem } } } - + IList TryInitMembers() { - lock (loader.currentModuleMetadata) { + lock (loader.currentModule) { if (this.members != null) return this.members; var result = new List(); - var td = typeDefinition.This(); + var td = module.GetTypeDefinition((TypeDefinitionHandle)MetadataToken); loader.InitMembers(td, this, result); return FreezableHelper.FreezeList(result); } @@ -1115,38 +1114,38 @@ namespace ICSharpCode.Decompiler.TypeSystem public IEnumerable Methods { get { return Members.OfType(); } } - + public IEnumerable Properties { get { return Members.OfType(); } } - + public IEnumerable Fields { get { return Members.OfType(); } } - + public IEnumerable Events { get { return Members.OfType(); } } - + public bool AddDefaultConstructorIfRequired { get { return kind == TypeKind.Struct || kind == TypeKind.Enum; } } - + public bool? HasExtensionMethods { get { return flags[FlagHasExtensionMethods]; } // we always return true or false, never null. // FlagHasNoExtensionMethods is unused in LazyCecilTypeDefinition } - + public bool IsPartial { get { return false; } } - + public override object Clone() { throw new NotSupportedException(); } - + public IType Resolve(ITypeResolveContext context) { if (context == null) @@ -1156,26 +1155,26 @@ namespace ICSharpCode.Decompiler.TypeSystem return context.CurrentAssembly.GetTypeDefinition(this.FullTypeName) ?? (IType)new UnknownType(this.Namespace, this.Name, this.TypeParameters.Count); } - + public ITypeResolveContext CreateResolveContext(ITypeResolveContext parentContext) { return parentContext; } } #endregion - + #region Read Method public IUnresolvedMethod ReadMethod(MethodDefinitionHandle method, IUnresolvedTypeDefinition parentType, SymbolKind methodType = SymbolKind.Method) { return ReadMethod(method, parentType, methodType, null); } - + IUnresolvedMethod ReadMethod(MethodDefinitionHandle handle, IUnresolvedTypeDefinition parentType, SymbolKind methodType, IUnresolvedMember accessorOwner) { if (handle.IsNil) return null; - var method = currentModuleMetadata.GetMethodDefinition(handle); - DefaultUnresolvedMethod m = new DefaultUnresolvedMethod(parentType, currentModuleMetadata.GetString(method.Name)); + var method = currentModule.GetMethodDefinition(handle); + DefaultUnresolvedMethod m = new DefaultUnresolvedMethod(parentType, currentModule.GetString(method.Name)); m.SymbolKind = methodType; m.AccessorOwner = accessorOwner; m.HasBody = (method.Attributes & MethodAttributes.Abstract) == 0 && @@ -1187,14 +1186,14 @@ namespace ICSharpCode.Decompiler.TypeSystem var genParams = method.GetGenericParameters(); if (genParams.Count > 0) { for (int i = 0; i < genParams.Count; i++) { - var gp = currentModuleMetadata.GetGenericParameter(genParams[i]); + var gp = currentModule.GetGenericParameter(genParams[i]); if (gp.Index != i) throw new InvalidOperationException("gp.Index != i"); m.TypeParameters.Add(new DefaultUnresolvedTypeParameter( - SymbolKind.Method, i, currentModuleMetadata.GetString(gp.Name))); + SymbolKind.Method, i, currentModule.GetString(gp.Name))); } for (int i = 0; i < genParams.Count; i++) { - var gp = currentModuleMetadata.GetGenericParameter(genParams[i]); + var gp = currentModule.GetGenericParameter(genParams[i]); var tp = (DefaultUnresolvedTypeParameter)m.TypeParameters[i]; AddConstraints(tp, gp); AddAttributes(gp, tp); @@ -1202,12 +1201,12 @@ namespace ICSharpCode.Decompiler.TypeSystem } } - var declaringType = currentModuleMetadata.GetTypeDefinition(method.GetDeclaringType()); - var reader = currentModuleMetadata.GetBlobReader(method.Signature); + var declaringType = currentModule.GetTypeDefinition(method.GetDeclaringType()); + var reader = currentModule.GetBlobReader(method.Signature); var signature = method.DecodeSignature(new TypeReferenceSignatureDecoder(), default(Unit)); m.ReturnType = signature.ReturnType; - + if (HasAnyAttributes(method)) AddAttributes(method, m.Attributes, m.ReturnTypeAttributes); TranslateModifiers(handle, m); @@ -1217,13 +1216,13 @@ namespace ICSharpCode.Decompiler.TypeSystem m.Parameters.Add(ReadParameter(par, signature.ParameterTypes[j])); j++; } - + if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) { m.Parameters.Add(new DefaultUnresolvedParameter(SpecialType.ArgList, string.Empty)); } - + // mark as extension method if the attribute is set - if ((method.Attributes & MethodAttributes.Static) == MethodAttributes.Static && HasExtensionAttribute(currentModuleMetadata, method.GetCustomAttributes())) { + if ((method.Attributes & MethodAttributes.Static) == MethodAttributes.Static && HasExtensionAttribute(currentModule, method.GetCustomAttributes())) { m.IsExtensionMethod = true; } /* TODO overrides @@ -1241,21 +1240,21 @@ namespace ICSharpCode.Decompiler.TypeSystem } }*/ - FinishReadMember(m, new Metadata.MethodDefinition(currentModule, handle)); + FinishReadMember(m, handle); return m; } - - static bool HasExtensionAttribute(MetadataReader currentModuleMetadata, CustomAttributeHandleCollection attributes) + + static bool HasExtensionAttribute(MetadataReader currentModule, CustomAttributeHandleCollection attributes) { foreach (var h in attributes) { - var attr = currentModuleMetadata.GetCustomAttribute(h); - var type = attr.GetAttributeType(currentModuleMetadata); - if (type.GetFullTypeName(currentModuleMetadata).ToString() == "System.Runtime.CompilerServices.ExtensionAttribute") + var attr = currentModule.GetCustomAttribute(h); + var type = attr.GetAttributeType(currentModule); + if (type.GetFullTypeName(currentModule).ToString() == "System.Runtime.CompilerServices.ExtensionAttribute") return true; } return false; } - + bool IsVisible(MethodAttributes att) { att &= MethodAttributes.MemberAccessMask; @@ -1264,7 +1263,7 @@ namespace ICSharpCode.Decompiler.TypeSystem || att == MethodAttributes.Family || att == MethodAttributes.FamORAssem; } - + static Accessibility GetAccessibility(MethodAttributes attr) { switch (attr & MethodAttributes.MemberAccessMask) { @@ -1282,10 +1281,10 @@ namespace ICSharpCode.Decompiler.TypeSystem return Accessibility.Private; } } - + void TranslateModifiers(MethodDefinitionHandle handle, AbstractUnresolvedMember m) { - var method = currentModuleMetadata.GetMethodDefinition(handle); + var method = currentModule.GetMethodDefinition(handle); if (m.DeclaringTypeDefinition.Kind == TypeKind.Interface) { // interface members don't have modifiers, but we want to handle them as "public abstract" m.Accessibility = Accessibility.Public; @@ -1310,15 +1309,15 @@ namespace ICSharpCode.Decompiler.TypeSystem } } #endregion - + #region Read Parameter public IUnresolvedParameter ReadParameter(ParameterHandle handle, ITypeReference type) { if (handle.IsNil) throw new ArgumentNullException(nameof(handle)); - var parameter = currentModuleMetadata.GetParameter(handle); - var p = new DefaultUnresolvedParameter(type, interningProvider.Intern(currentModuleMetadata.GetString(parameter.Name))); - + var parameter = currentModule.GetParameter(handle); + var p = new DefaultUnresolvedParameter(type, interningProvider.Intern(currentModule.GetString(parameter.Name))); + if (type is ByReferenceTypeReference) { if ((parameter.Attributes & ParameterAttributes.In) == 0 && (parameter.Attributes & ParameterAttributes.Out) != 0) p.IsOut = true; @@ -1326,30 +1325,30 @@ namespace ICSharpCode.Decompiler.TypeSystem p.IsRef = true; } AddAttributes(parameter, p); - + if ((parameter.Attributes & ParameterAttributes.Optional) != 0) { var constantHandle = parameter.GetDefaultValue(); if (!constantHandle.IsNil) { - var constant = currentModuleMetadata.GetConstant(constantHandle); - var blobReader = currentModuleMetadata.GetBlobReader(constant.Value); + var constant = currentModule.GetConstant(constantHandle); + var blobReader = currentModule.GetBlobReader(constant.Value); p.DefaultValue = CreateSimpleConstantValue(type, blobReader.ReadConstant(constant.TypeCode)); } } - + if (type is ArrayTypeReference) { foreach (CustomAttributeHandle h in parameter.GetCustomAttributes()) { - var att = currentModuleMetadata.GetCustomAttribute(h); - if (att.GetAttributeType(currentModuleMetadata).GetFullTypeName(currentModuleMetadata).ToString() == typeof(ParamArrayAttribute).FullName) { + var att = currentModule.GetCustomAttribute(h); + if (att.GetAttributeType(currentModule).GetFullTypeName(currentModule).ToString() == typeof(ParamArrayAttribute).FullName) { p.IsParams = true; break; } } } - + return interningProvider.Intern(p); } #endregion - + #region Read Field bool IsVisible(FieldAttributes att) { @@ -1396,7 +1395,7 @@ namespace ICSharpCode.Decompiler.TypeSystem return new decimal((int)ctorArgs[4], (int)ctorArgs[3], (int)ctorArgs[2], (byte)ctorArgs[1] != 0, (byte)ctorArgs[0]); } */ - + public IUnresolvedField ReadField(FieldDefinitionHandle handle, IUnresolvedTypeDefinition parentType) { if (handle.IsNil) @@ -1404,16 +1403,16 @@ namespace ICSharpCode.Decompiler.TypeSystem if (parentType == null) throw new ArgumentNullException(nameof(parentType)); - var field = currentModuleMetadata.GetFieldDefinition(handle); - DefaultUnresolvedField f = new DefaultUnresolvedField(parentType, currentModuleMetadata.GetString(field.Name)); + var field = currentModule.GetFieldDefinition(handle); + DefaultUnresolvedField f = new DefaultUnresolvedField(parentType, currentModule.GetString(field.Name)); f.Accessibility = GetAccessibility(field.Attributes); f.IsReadOnly = (field.Attributes & FieldAttributes.InitOnly) == FieldAttributes.InitOnly; f.IsStatic = (field.Attributes & FieldAttributes.Static) == FieldAttributes.Static; f.ReturnType = ResolveDynamicTypes(field.DecodeSignature(new TypeReferenceSignatureDecoder(), default(Unit)), field.GetCustomAttributes()); var constantHandle = field.GetDefaultValue(); if (!constantHandle.IsNil) { - var constant = currentModuleMetadata.GetConstant(constantHandle); - var blobReader = currentModuleMetadata.GetBlobReader(constant.Value); + var constant = currentModule.GetConstant(constantHandle); + var blobReader = currentModule.GetBlobReader(constant.Value); f.ConstantValue = CreateSimpleConstantValue(f.ReturnType, blobReader.ReadConstant(constant.TypeCode)); } else { // TODO decimal constants @@ -1433,10 +1432,10 @@ namespace ICSharpCode.Decompiler.TypeSystem f.IsVolatile = true; } - FinishReadMember(f, new Metadata.FieldDefinition(currentModule, handle)); + FinishReadMember(f, handle); return f; } - + static Accessibility GetAccessibility(FieldAttributes attr) { switch (attr & FieldAttributes.FieldAccessMask) { @@ -1515,9 +1514,9 @@ namespace ICSharpCode.Decompiler.TypeSystem bool HasDynamicAttribute(CustomAttributeHandleCollection attributes, int typeIndex) { foreach (CustomAttributeHandle handle in attributes) { - var a = currentModuleMetadata.GetCustomAttribute(handle); - var type = a.GetAttributeType(currentModuleMetadata); - if (type.GetFullTypeName(currentModuleMetadata).ToString() == "System.Runtime.CompilerServices.DynamicAttribute") { + var a = currentModule.GetCustomAttribute(handle); + var type = a.GetAttributeType(currentModule); + if (type.GetFullTypeName(currentModule).ToString() == "System.Runtime.CompilerServices.DynamicAttribute") { var ctor = a.DecodeValue(new TypeSystemAttributeTypeProvider(minimalCorlibContext)); if (ctor.FixedArguments.Length == 1) { if (ctor.FixedArguments[0].Value is bool[] values && typeIndex < values.Length) @@ -1541,21 +1540,21 @@ namespace ICSharpCode.Decompiler.TypeSystem tp.Variance = VarianceModifier.Covariant; break; } - + tp.HasReferenceTypeConstraint = (g.Attributes & GenericParameterAttributes.ReferenceTypeConstraint) != 0; tp.HasValueTypeConstraint = (g.Attributes & GenericParameterAttributes.NotNullableValueTypeConstraint) != 0; tp.HasDefaultConstructorConstraint = (g.Attributes & GenericParameterAttributes.DefaultConstructorConstraint) != 0; - + foreach (GenericParameterConstraintHandle h in g.GetConstraints()) { - var constraint = currentModuleMetadata.GetGenericParameterConstraint(h); + var constraint = currentModule.GetGenericParameterConstraint(h); tp.Constraints.Add(ReadTypeReference(constraint.Type)); } } #endregion - + #region Read Property - Accessibility MergePropertyAccessibility (Accessibility left, Accessibility right) + Accessibility MergePropertyAccessibility(Accessibility left, Accessibility right) { if (left == Accessibility.Public || right == Accessibility.Public) return Accessibility.Public; @@ -1585,30 +1584,30 @@ namespace ICSharpCode.Decompiler.TypeSystem throw new ArgumentNullException(nameof(handle)); if (parentType == null) throw new ArgumentNullException(nameof(parentType)); - var property = currentModuleMetadata.GetPropertyDefinition(handle); - var propertyName = currentModuleMetadata.GetString(property.Name); + var property = currentModule.GetPropertyDefinition(handle); + var propertyName = currentModule.GetString(property.Name); DefaultUnresolvedProperty p = new DefaultUnresolvedProperty(parentType, propertyName); p.SymbolKind = propertyType; var accessors = property.GetAccessors(); TranslateModifiers(accessors.Getter.IsNil ? accessors.Setter : accessors.Getter, p); if (!accessors.Getter.IsNil && !accessors.Setter.IsNil) - p.Accessibility = MergePropertyAccessibility(GetAccessibility(currentModuleMetadata.GetMethodDefinition(accessors.Getter).Attributes), GetAccessibility (currentModuleMetadata.GetMethodDefinition(accessors.Setter).Attributes)); + p.Accessibility = MergePropertyAccessibility(GetAccessibility(currentModule.GetMethodDefinition(accessors.Getter).Attributes), GetAccessibility(currentModule.GetMethodDefinition(accessors.Setter).Attributes)); var signature = property.DecodeSignature(new TypeReferenceSignatureDecoder(), default(Unit)); p.ReturnType = signature.ReturnType; - + p.Getter = ReadMethod(accessors.Getter, parentType, SymbolKind.Accessor, p); p.Setter = ReadMethod(accessors.Setter, parentType, SymbolKind.Accessor, p); ParameterHandleCollection parameterHandles = default(ParameterHandleCollection); int parameterCount = 0; if (!accessors.Getter.IsNil) { - var getter = currentModuleMetadata.GetMethodDefinition(accessors.Getter); + var getter = currentModule.GetMethodDefinition(accessors.Getter); parameterHandles = getter.GetParameters(); parameterCount = parameterHandles.Count; } else { if (!accessors.Setter.IsNil) { - var setter = currentModuleMetadata.GetMethodDefinition(accessors.Setter); + var setter = currentModule.GetMethodDefinition(accessors.Setter); parameterHandles = setter.GetParameters(); parameterCount = parameterHandles.Count - 1; } @@ -1632,11 +1631,11 @@ namespace ICSharpCode.Decompiler.TypeSystem } } - FinishReadMember(p, new Metadata.PropertyDefinition(currentModule, handle)); + FinishReadMember(p, handle); return p; } #endregion - + #region Read Event public IUnresolvedEvent ReadEvent(EventDefinitionHandle ev, IUnresolvedTypeDefinition parentType) { @@ -1645,20 +1644,20 @@ namespace ICSharpCode.Decompiler.TypeSystem if (parentType == null) throw new ArgumentNullException(nameof(parentType)); - var ed = currentModuleMetadata.GetEventDefinition(ev); - var eventName = currentModuleMetadata.GetString(ed.Name); + var ed = currentModule.GetEventDefinition(ev); + var eventName = currentModule.GetString(ed.Name); DefaultUnresolvedEvent e = new DefaultUnresolvedEvent(parentType, eventName); var accessors = ed.GetAccessors(); TranslateModifiers(accessors.Adder, e); e.ReturnType = ReadTypeReference(ed.Type, typeAttributes: ed.GetCustomAttributes()); - + e.AddAccessor = ReadMethod(accessors.Adder, parentType, SymbolKind.Accessor, e); e.RemoveAccessor = ReadMethod(accessors.Remover, parentType, SymbolKind.Accessor, e); e.InvokeAccessor = ReadMethod(accessors.Raiser, parentType, SymbolKind.Accessor, e); - + AddAttributes(ed, e); - + var accessor = e.AddAccessor ?? e.RemoveAccessor ?? e.InvokeAccessor; if (accessor != null && accessor.IsExplicitInterfaceImplementation) { if (ShortenInterfaceImplNames) @@ -1669,96 +1668,27 @@ namespace ICSharpCode.Decompiler.TypeSystem } } - FinishReadMember(e, new Metadata.EventDefinition(currentModule, ev)); - + FinishReadMember(e, ev); + return e; } #endregion - + #region FinishReadMember / Interning - void FinishReadMember(AbstractUnresolvedMember member, Metadata.IMetadataEntity cecilDefinition) + void FinishReadMember(AbstractUnresolvedMember member, EntityHandle cecilDefinition) { + member.MetadataToken = cecilDefinition; member.ApplyInterningProvider(interningProvider); member.Freeze(); RegisterCecilObject(member, cecilDefinition); } #endregion - + #region Type system translation table - readonly Dictionary typeSystemTranslationTable; - - void RegisterCecilObject(IUnresolvedEntity typeSystemObject, Metadata.IMetadataEntity cecilObject) + void RegisterCecilObject(IUnresolvedEntity typeSystemObject, EntityHandle cecilObject) { OnEntityLoaded?.Invoke(typeSystemObject, cecilObject); - - AddToTypeSystemTranslationTable(typeSystemObject, cecilObject); - } - - void AddToTypeSystemTranslationTable(object typeSystemObject, Metadata.IMetadataEntity cecilObject) - { - if (typeSystemTranslationTable != null) { - // When lazy-loading, the dictionary might be shared between multiple cecil-loaders that are used concurrently - lock (typeSystemTranslationTable) { - typeSystemTranslationTable[typeSystemObject] = cecilObject; - } - } - } - - T InternalGetCecilObject (object typeSystemObject) where T : Metadata.IMetadataEntity - { - if (typeSystemObject == null) - throw new ArgumentNullException ("typeSystemObject"); - if (!HasCecilReferences) - throw new NotSupportedException ("This instance contains no cecil references."); - Metadata.IMetadataEntity result; - lock (typeSystemTranslationTable) { - if (!typeSystemTranslationTable.TryGetValue (typeSystemObject, out result)) - return default(T); - } - return (T)result; - } - - public AssemblyDefinition GetCecilObject (IUnresolvedAssembly content) - { - throw new NotImplementedException(); - //return InternalGetCecilObject (content); - } - - - public TypeDefinition GetCecilObject (IUnresolvedTypeDefinition type) - { - if (type == null) - throw new ArgumentNullException ("type"); - throw new NotImplementedException(); - //return InternalGetCecilObject (type); } - - - public MethodDefinition GetCecilObject (IUnresolvedMethod method) - { - throw new NotImplementedException(); - //return InternalGetCecilObject (method); - } - - - public FieldDefinition GetCecilObject (IUnresolvedField field) - { - throw new NotImplementedException(); - //return InternalGetCecilObject (field); - } - - - public EventDefinition GetCecilObject (IUnresolvedEvent evt) - { - throw new NotImplementedException(); - //return InternalGetCecilObject (evt); - } - - - public PropertyDefinition GetCecilObject (IUnresolvedProperty property) - { - throw new NotImplementedException(); - //return InternalGetCecilObject (property); } #endregion } diff --git a/ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs index 970cb8c66..7f7c6b241 100644 --- a/ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs +++ b/ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs @@ -51,22 +51,22 @@ namespace ICSharpCode.Decompiler.TypeSystem get { return substitution; } } - public IType Resolve(Mono.Cecil.TypeReference typeReference) + public IType ResolveAsType(System.Reflection.Metadata.EntityHandle typeReference) { - return context.Resolve(typeReference).AcceptVisitor(substitution); + return context.ResolveAsType(typeReference).AcceptVisitor(substitution); } - public IField Resolve(Mono.Cecil.FieldReference fieldReference) + public IField ResolveAsField(System.Reflection.Metadata.EntityHandle fieldReference) { - IField field = context.Resolve(fieldReference); + IField field = context.ResolveAsField(fieldReference); if (field != null) field = (IField)field.Specialize(substitution); return field; } - public IMethod Resolve(Mono.Cecil.MethodReference methodReference) + public IMethod ResolveAsMethod(System.Reflection.Metadata.EntityHandle methodReference) { - IMethod method = context.Resolve(methodReference); + IMethod method = context.ResolveAsMethod(methodReference); if (method != null) method = (IMethod)method.Specialize(substitution); return method; diff --git a/ICSharpCode.Decompiler/Util/CollectionExtensions.cs b/ICSharpCode.Decompiler/Util/CollectionExtensions.cs index 911e4561a..beaba4ffd 100644 --- a/ICSharpCode.Decompiler/Util/CollectionExtensions.cs +++ b/ICSharpCode.Decompiler/Util/CollectionExtensions.cs @@ -138,10 +138,19 @@ namespace ICSharpCode.Decompiler.Util public static IEnumerable SelectWithIndex(this IEnumerable source, Func func) { int index = 0; - foreach (var element in source) + foreach (var element in source) yield return func(index++, element); } - + + public static IEnumerable<(int, T)> WithIndex(this ICollection source) + { + int index = 0; + foreach (var item in source) { + yield return (index, item); + index++; + } + } + /// /// The merge step of merge sort. /// diff --git a/ILSpy/SearchStrategies.cs b/ILSpy/SearchStrategies.cs index 2b149b3bd..0c8852a8f 100644 --- a/ILSpy/SearchStrategies.cs +++ b/ILSpy/SearchStrategies.cs @@ -422,7 +422,7 @@ namespace ICSharpCode.ILSpy return true; break; case ILOpCode.Ldstr: - if ((string)searchTermLiteralValue == ILParser.DecodeUserString(ref blob, module)) + if ((string)searchTermLiteralValue == ILParser.DecodeUserString(ref blob, metadata)) return true; break; } @@ -434,7 +434,7 @@ namespace ICSharpCode.ILSpy ILParser.SkipOperand(ref blob, code); continue; } - if (IsMatch(t => ILParser.DecodeUserString(ref blob, module))) + if (IsMatch(t => ILParser.DecodeUserString(ref blob, metadata))) return true; } }