diff --git a/ICSharpCode.Decompiler/CSharp/Annotations.cs b/ICSharpCode.Decompiler/CSharp/Annotations.cs index 0cf8525d4..cfd05f99a 100644 --- a/ICSharpCode.Decompiler/CSharp/Annotations.cs +++ b/ICSharpCode.Decompiler/CSharp/Annotations.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; +using System.Linq; using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Semantics; @@ -154,6 +155,22 @@ namespace ICSharpCode.Decompiler.CSharp loop.AddAnnotation(new ILVariableResolveResult(v, v.Type)); return loop; } + + public static T CopyAnnotationsFrom(this T node, AstNode other) where T : AstNode + { + foreach (object annotation in other.Annotations) { + node.AddAnnotation(annotation); + } + return node; + } + + public static T CopyInstructionsFrom(this T node, AstNode other) where T : AstNode + { + foreach (object annotation in other.Annotations.OfType()) { + node.AddAnnotation(annotation); + } + return node; + } } public class ILVariableResolveResult : ResolveResult diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index 4acee1656..4f08d5726 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -235,7 +235,7 @@ namespace ICSharpCode.Decompiler.CSharp case HandleKind.MethodDefinition: var methodHandle = (MethodDefinitionHandle)member; var method = metadata.GetMethodDefinition(methodHandle); - var methodSemantics = ((MethodDefinitionHandle)member).GetMethodSemanticsAttributes(metadata); + var methodSemantics = module.MethodSemanticsLookup.GetSemantics(methodHandle).Item2; if (methodSemantics != 0 && methodSemantics != System.Reflection.MethodSemanticsAttributes.Other) return true; if (settings.AnonymousMethods && methodHandle.HasGeneratedName(metadata) && methodHandle.IsCompilerGenerated(metadata)) diff --git a/ICSharpCode.Decompiler/CSharp/NRefactoryExtensions.cs b/ICSharpCode.Decompiler/CSharp/NRefactoryExtensions.cs deleted file mode 100644 index 4104ac02b..000000000 --- a/ICSharpCode.Decompiler/CSharp/NRefactoryExtensions.cs +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -using System; -using System.Linq; -using ICSharpCode.Decompiler.CSharp.Syntax; -using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching; -using ICSharpCode.Decompiler.IL; - -namespace ICSharpCode.Decompiler.CSharp -{ - static class NRefactoryExtensions - { - [Obsolete("Use the more concrete With...()-methods in AnnotationExtensions, so that we maintain a centralised list of the possible annotation types")] - public static T WithAnnotation(this T node, object annotation) where T : AstNode - { - if (annotation != null) - node.AddAnnotation(annotation); - return node; - } - - public static T CopyAnnotationsFrom(this T node, AstNode other) where T : AstNode - { - foreach (object annotation in other.Annotations) { - node.AddAnnotation(annotation); - } - return node; - } - - public static T CopyInstructionsFrom(this T node, AstNode other) where T : AstNode - { - foreach (object annotation in other.Annotations.OfType()) { - node.AddAnnotation(annotation); - } - return node; - } - - public static T Detach(this T node) where T : AstNode - { - node.Remove(); - return node; - } - - public static Expression WithName(this Expression node, string patternGroupName) - { - return new NamedNode(patternGroupName, node); - } - - public static Statement WithName(this Statement node, string patternGroupName) - { - return new NamedNode(patternGroupName, node); - } - - public static void AddNamedArgument(this Syntax.Attribute attribute, string name, Expression argument) - { - attribute.Arguments.Add(new AssignmentExpression(new IdentifierExpression(name), argument)); - } - - public static AstType ToType(this Pattern pattern) - { - return pattern; - } - - public static Expression ToExpression(this Pattern pattern) - { - return pattern; - } - - public static Statement ToStatement(this Pattern pattern) - { - return pattern; - } - - public static Statement GetNextStatement(this Statement statement) - { - AstNode next = statement.NextSibling; - while (next != null && !(next is Statement)) - next = next.NextSibling; - return (Statement)next; - } - - public static bool IsArgList(this AstType type) - { - var simpleType = type as SimpleType; - return simpleType != null && simpleType.Identifier == "__arglist"; - } - - /// - /// Returns true if is bitwise and, bitwise or, or exclusive or. - /// - public static bool IsBitwise(this BinaryOperatorType operatorType) - { - return operatorType == BinaryOperatorType.BitwiseAnd - || operatorType == BinaryOperatorType.BitwiseOr - || operatorType == BinaryOperatorType.ExclusiveOr; - } - } -} diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/INode.cs b/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/INode.cs index 3e0a9b73f..3eab26de3 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/INode.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/PatternMatching/INode.cs @@ -65,5 +65,30 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching throw new ArgumentNullException("pattern"); return pattern.DoMatch(other, PatternMatching.Match.CreateNew()); } + + public static AstType ToType(this Pattern pattern) + { + return pattern; + } + + public static Expression ToExpression(this Pattern pattern) + { + return pattern; + } + + public static Statement ToStatement(this Pattern pattern) + { + return pattern; + } + + public static Expression WithName(this Expression node, string patternGroupName) + { + return new NamedNode(patternGroupName, node); + } + + public static Statement WithName(this Statement node, string patternGroupName) + { + return new NamedNode(patternGroupName, node); + } } } diff --git a/ICSharpCode.Decompiler/CSharp/Syntax/SyntaxExtensions.cs b/ICSharpCode.Decompiler/CSharp/Syntax/SyntaxExtensions.cs index 858446041..b4ffe1f74 100644 --- a/ICSharpCode.Decompiler/CSharp/Syntax/SyntaxExtensions.cs +++ b/ICSharpCode.Decompiler/CSharp/Syntax/SyntaxExtensions.cs @@ -40,5 +40,40 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax return false; } } + + /// + /// Returns true if is bitwise and, bitwise or, or exclusive or. + /// + public static bool IsBitwise(this BinaryOperatorType operatorType) + { + return operatorType == BinaryOperatorType.BitwiseAnd + || operatorType == BinaryOperatorType.BitwiseOr + || operatorType == BinaryOperatorType.ExclusiveOr; + } + + public static Statement GetNextStatement(this Statement statement) + { + AstNode next = statement.NextSibling; + while (next != null && !(next is Statement)) + next = next.NextSibling; + return (Statement)next; + } + + public static bool IsArgList(this AstType type) + { + var simpleType = type as SimpleType; + return simpleType != null && simpleType.Identifier == "__arglist"; + } + + public static void AddNamedArgument(this Syntax.Attribute attribute, string name, Expression argument) + { + attribute.Arguments.Add(new AssignmentExpression(new IdentifierExpression(name), argument)); + } + + public static T Detach(this T node) where T : AstNode + { + node.Remove(); + return node; + } } } diff --git a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs index 6a9ed063b..acc0f2526 100644 --- a/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs +++ b/ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection.Metadata; using System.Text; +using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Util; using SRM = System.Reflection.Metadata; diff --git a/ICSharpCode.Decompiler/Disassembler/DomExtensions.cs b/ICSharpCode.Decompiler/Disassembler/DomExtensions.cs deleted file mode 100644 index ecde19ff1..000000000 --- a/ICSharpCode.Decompiler/Disassembler/DomExtensions.cs +++ /dev/null @@ -1,322 +0,0 @@ -// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. - -using System; -using System.Collections.Immutable; -using System.Reflection; -using System.Reflection.Metadata; -using SRM = System.Reflection.Metadata; -using System.Reflection.Metadata.Ecma335; - -using ICSharpCode.Decompiler.Metadata; -using ICSharpCode.Decompiler.Util; - -namespace ICSharpCode.Decompiler.Disassembler -{ - public static class MetadataExtensions - { - public static void WriteTo(this EntityHandle entity, PEFile module, ITextOutput output, GenericContext genericContext, ILNameSyntax syntax = ILNameSyntax.Signature) - { - if (entity.IsNil) - throw new ArgumentNullException(nameof(entity)); - if (module == null) - throw new ArgumentNullException(nameof(module)); - var metadata = module.Metadata; - Action signature; - MethodSignature> methodSignature; - string memberName; - switch (entity.Kind) { - case HandleKind.TypeDefinition: { - var td = metadata.GetTypeDefinition((TypeDefinitionHandle)entity); - output.WriteReference(module, entity, td.GetFullTypeName(metadata).ToILNameString()); - break; - } - case HandleKind.TypeReference: { - var tr = metadata.GetTypeReference((TypeReferenceHandle)entity); - if (!tr.ResolutionScope.IsNil) { - output.Write("["); - var currentTypeRef = tr; - while (currentTypeRef.ResolutionScope.Kind == HandleKind.TypeReference) { - currentTypeRef = metadata.GetTypeReference((TypeReferenceHandle)currentTypeRef.ResolutionScope); - } - switch (currentTypeRef.ResolutionScope.Kind) { - case HandleKind.ModuleDefinition: - var modDef = metadata.GetModuleDefinition(); - output.Write(DisassemblerHelpers.Escape(metadata.GetString(modDef.Name))); - break; - case HandleKind.ModuleReference: - break; - case HandleKind.AssemblyReference: - var asmRef = metadata.GetAssemblyReference((AssemblyReferenceHandle)currentTypeRef.ResolutionScope); - output.Write(DisassemblerHelpers.Escape(metadata.GetString(asmRef.Name))); - break; - } - output.Write("]"); - } - output.WriteReference(module, entity, entity.GetFullTypeName(metadata).ToILNameString()); - break; - } - case HandleKind.TypeSpecification: { - var ts = metadata.GetTypeSpecification((TypeSpecificationHandle)entity); - signature = ts.DecodeSignature(new DisassemblerSignatureProvider(module, output), genericContext); - signature(syntax); - break; - } - case HandleKind.FieldDefinition: { - var fd = metadata.GetFieldDefinition((FieldDefinitionHandle)entity); - signature = fd.DecodeSignature(new DisassemblerSignatureProvider(module, output), new GenericContext(fd.GetDeclaringType(), module)); - signature(ILNameSyntax.SignatureNoNamedTypeParameters); - output.Write(' '); - ((EntityHandle)fd.GetDeclaringType()).WriteTo(module, output, GenericContext.Empty, ILNameSyntax.TypeName); - output.Write("::"); - output.WriteReference(module, entity, DisassemblerHelpers.Escape(metadata.GetString(fd.Name))); - break; - } - case HandleKind.MethodDefinition: { - var md = metadata.GetMethodDefinition((MethodDefinitionHandle)entity); - methodSignature = md.DecodeSignature(new DisassemblerSignatureProvider(module, output), new GenericContext((MethodDefinitionHandle)entity, module)); - if (methodSignature.Header.HasExplicitThis) { - output.Write("instance explicit "); - } else if (methodSignature.Header.IsInstance) { - output.Write("instance "); - } - if (methodSignature.Header.CallingConvention == SignatureCallingConvention.VarArgs) { - output.Write("vararg "); - } - methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters); - output.Write(' '); - var declaringType = md.GetDeclaringType(); - if (!declaringType.IsNil) { - ((EntityHandle)declaringType).WriteTo(module, output, genericContext, ILNameSyntax.TypeName); - output.Write("::"); - } - bool isCompilerControlled = (md.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope; - if (isCompilerControlled) { - output.WriteReference(module, entity, DisassemblerHelpers.Escape(metadata.GetString(md.Name) + "$PST" + MetadataTokens.GetToken(entity).ToString("X8"))); - } else { - output.WriteReference(module, entity, DisassemblerHelpers.Escape(metadata.GetString(md.Name))); - } - var genericParameters = md.GetGenericParameters(); - if (genericParameters.Count > 0) { - output.Write('<'); - for (int i = 0; i < genericParameters.Count; i++) { - if (i > 0) - output.Write(", "); - var gp = metadata.GetGenericParameter(genericParameters[i]); - if ((gp.Attributes & GenericParameterAttributes.ReferenceTypeConstraint) == GenericParameterAttributes.ReferenceTypeConstraint) { - output.Write("class "); - } else if ((gp.Attributes & GenericParameterAttributes.NotNullableValueTypeConstraint) == GenericParameterAttributes.NotNullableValueTypeConstraint) { - output.Write("valuetype "); - } - if ((gp.Attributes & GenericParameterAttributes.DefaultConstructorConstraint) == GenericParameterAttributes.DefaultConstructorConstraint) { - output.Write(".ctor "); - } - var constraints = gp.GetConstraints(); - if (constraints.Count > 0) { - output.Write('('); - for (int j = 0; j < constraints.Count; j++) { - if (j > 0) - output.Write(", "); - var constraint = metadata.GetGenericParameterConstraint(constraints[j]); - constraint.Type.WriteTo(module, output, new GenericContext((MethodDefinitionHandle)entity, module), ILNameSyntax.TypeName); - } - output.Write(") "); - } - if ((gp.Attributes & GenericParameterAttributes.Contravariant) == GenericParameterAttributes.Contravariant) { - output.Write('-'); - } else if ((gp.Attributes & GenericParameterAttributes.Covariant) == GenericParameterAttributes.Covariant) { - output.Write('+'); - } - output.Write(DisassemblerHelpers.Escape(metadata.GetString(gp.Name))); - } - output.Write('>'); - } - output.Write("("); - for (int i = 0; i < methodSignature.ParameterTypes.Length; ++i) { - if (i > 0) - output.Write(", "); - methodSignature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters); - } - output.Write(")"); - break; - } - case HandleKind.MemberReference: - var mr = metadata.GetMemberReference((MemberReferenceHandle)entity); - memberName = metadata.GetString(mr.Name); - switch (mr.GetKind()) { - case MemberReferenceKind.Method: - methodSignature = mr.DecodeMethodSignature(new DisassemblerSignatureProvider(module, output), genericContext); - if (methodSignature.Header.HasExplicitThis) { - output.Write("instance explicit "); - } else if (methodSignature.Header.IsInstance) { - output.Write("instance "); - } - if (methodSignature.Header.CallingConvention == SignatureCallingConvention.VarArgs) { - output.Write("vararg "); - } - methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters); - output.Write(' '); - WriteParent(output, module, metadata, mr.Parent, genericContext, syntax); - output.Write("::"); - output.WriteReference(module, entity, DisassemblerHelpers.Escape(memberName)); - output.Write("("); - for (int i = 0; i < methodSignature.ParameterTypes.Length; ++i) { - if (i > 0) - output.Write(", "); - if (i == methodSignature.RequiredParameterCount) - output.Write("..., "); - methodSignature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters); - } - output.Write(")"); - break; - case MemberReferenceKind.Field: - var fieldSignature = mr.DecodeFieldSignature(new DisassemblerSignatureProvider(module, output), genericContext); - fieldSignature(ILNameSyntax.SignatureNoNamedTypeParameters); - output.Write(' '); - WriteParent(output, module, metadata, mr.Parent, genericContext, syntax); - output.Write("::"); - output.WriteReference(module, entity, DisassemblerHelpers.Escape(memberName)); - break; - } - break; - case HandleKind.MethodSpecification: - var ms = metadata.GetMethodSpecification((MethodSpecificationHandle)entity); - var substitution = ms.DecodeSignature(new DisassemblerSignatureProvider(module, output), genericContext); - switch (ms.Method.Kind) { - case HandleKind.MethodDefinition: - var methodDefinition = metadata.GetMethodDefinition((MethodDefinitionHandle)ms.Method); - var methodName = metadata.GetString(methodDefinition.Name); - methodSignature = methodDefinition.DecodeSignature(new DisassemblerSignatureProvider(module, output), genericContext); - if (methodSignature.Header.HasExplicitThis) { - output.Write("instance explicit "); - } else if (methodSignature.Header.IsInstance) { - output.Write("instance "); - } - if (methodSignature.Header.CallingConvention == SignatureCallingConvention.VarArgs) { - output.Write("vararg "); - } - methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters); - output.Write(' '); - var declaringType = methodDefinition.GetDeclaringType(); - if (!declaringType.IsNil) { - ((EntityHandle)declaringType).WriteTo(module, output, genericContext, ILNameSyntax.TypeName); - output.Write("::"); - } - bool isCompilerControlled = (methodDefinition.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope; - if (isCompilerControlled) { - output.Write(DisassemblerHelpers.Escape(methodName + "$PST" + MetadataTokens.GetToken(ms.Method).ToString("X8"))); - } else { - output.Write(DisassemblerHelpers.Escape(methodName)); - } - output.Write('<'); - for (int i = 0; i < substitution.Length; i++) { - if (i > 0) - output.Write(", "); - substitution[i](syntax); - } - output.Write('>'); - output.Write("("); - for (int i = 0; i < methodSignature.ParameterTypes.Length; ++i) { - if (i > 0) - output.Write(", "); - methodSignature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters); - } - output.Write(")"); - break; - case HandleKind.MemberReference: - var memberReference = metadata.GetMemberReference((MemberReferenceHandle)ms.Method); - memberName = metadata.GetString(memberReference.Name); - methodSignature = memberReference.DecodeMethodSignature(new DisassemblerSignatureProvider(module, output), genericContext); - if (methodSignature.Header.HasExplicitThis) { - output.Write("instance explicit "); - } else if (methodSignature.Header.IsInstance) { - output.Write("instance "); - } - if (methodSignature.Header.CallingConvention == SignatureCallingConvention.VarArgs) { - output.Write("vararg "); - } - methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters); - output.Write(' '); - WriteParent(output, module, metadata, memberReference.Parent, genericContext, syntax); - output.Write("::"); - output.Write(DisassemblerHelpers.Escape(memberName)); - output.Write('<'); - for (int i = 0; i < substitution.Length; i++) { - if (i > 0) - output.Write(", "); - substitution[i](syntax); - } - output.Write('>'); - output.Write("("); - for (int i = 0; i < methodSignature.ParameterTypes.Length; ++i) { - if (i > 0) - output.Write(", "); - methodSignature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters); - } - output.Write(")"); - break; - } - break; - case HandleKind.StandaloneSignature: - var standaloneSig = metadata.GetStandaloneSignature((StandaloneSignatureHandle)entity); - switch (standaloneSig.GetKind()) { - case StandaloneSignatureKind.Method: - var methodSig = standaloneSig.DecodeMethodSignature(new DisassemblerSignatureProvider(module, output), genericContext); - methodSig.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters); - output.Write('('); - for (int i = 0; i < methodSig.ParameterTypes.Length; i++) { - if (i > 0) - output.Write(", "); - methodSig.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters); - } - output.Write(')'); - break; - case StandaloneSignatureKind.LocalVariables: - default: - output.Write($"@{MetadataTokens.GetToken(entity):X8} /* signature {standaloneSig.GetKind()} */"); - break; - } - break; - default: - output.Write($"@{MetadataTokens.GetToken(entity):X8}"); - break; - } - } - - static void WriteParent(ITextOutput output, PEFile module, MetadataReader metadata, EntityHandle parentHandle, GenericContext genericContext, ILNameSyntax syntax) - { - switch (parentHandle.Kind) { - case HandleKind.MethodDefinition: - var methodDef = metadata.GetMethodDefinition((MethodDefinitionHandle)parentHandle); - ((EntityHandle)methodDef.GetDeclaringType()).WriteTo(module, output, genericContext, syntax); - break; - case HandleKind.ModuleReference: - output.Write('['); - var moduleRef = metadata.GetModuleReference((ModuleReferenceHandle)parentHandle); - output.Write(metadata.GetString(moduleRef.Name)); - output.Write(']'); - break; - case HandleKind.TypeDefinition: - case HandleKind.TypeReference: - case HandleKind.TypeSpecification: - parentHandle.WriteTo(module, output, genericContext, syntax); - break; - } - } - } -} \ No newline at end of file diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index 8e6aa6a94..769242a61 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -256,7 +256,6 @@ - @@ -267,7 +266,6 @@ - diff --git a/ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs b/ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs index 04fa15161..384c335c1 100644 --- a/ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs +++ b/ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs @@ -16,7 +16,12 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using System; +using System.Reflection; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler.Disassembler; +using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; @@ -61,5 +66,295 @@ namespace ICSharpCode.Decompiler.IL else output.Write($"[{interval.Start:x4}..{interval.InclusiveEnd:x4}] "); } + + public static void WriteTo(this EntityHandle entity, PEFile module, ITextOutput output, Metadata.GenericContext genericContext, ILNameSyntax syntax = ILNameSyntax.Signature) + { + if (entity.IsNil) + throw new ArgumentNullException(nameof(entity)); + if (module == null) + throw new ArgumentNullException(nameof(module)); + var metadata = module.Metadata; + Action signature; + MethodSignature> methodSignature; + string memberName; + switch (entity.Kind) { + case HandleKind.TypeDefinition: { + var td = metadata.GetTypeDefinition((TypeDefinitionHandle)entity); + output.WriteReference(module, entity, td.GetFullTypeName(metadata).ToILNameString()); + break; + } + case HandleKind.TypeReference: { + var tr = metadata.GetTypeReference((TypeReferenceHandle)entity); + if (!tr.ResolutionScope.IsNil) { + output.Write("["); + var currentTypeRef = tr; + while (currentTypeRef.ResolutionScope.Kind == HandleKind.TypeReference) { + currentTypeRef = metadata.GetTypeReference((TypeReferenceHandle)currentTypeRef.ResolutionScope); + } + switch (currentTypeRef.ResolutionScope.Kind) { + case HandleKind.ModuleDefinition: + var modDef = metadata.GetModuleDefinition(); + output.Write(DisassemblerHelpers.Escape(metadata.GetString(modDef.Name))); + break; + case HandleKind.ModuleReference: + break; + case HandleKind.AssemblyReference: + var asmRef = metadata.GetAssemblyReference((AssemblyReferenceHandle)currentTypeRef.ResolutionScope); + output.Write(DisassemblerHelpers.Escape(metadata.GetString(asmRef.Name))); + break; + } + output.Write("]"); + } + output.WriteReference(module, entity, entity.GetFullTypeName(metadata).ToILNameString()); + break; + } + case HandleKind.TypeSpecification: { + var ts = metadata.GetTypeSpecification((TypeSpecificationHandle)entity); + signature = ts.DecodeSignature(new DisassemblerSignatureProvider(module, output), genericContext); + signature(syntax); + break; + } + case HandleKind.FieldDefinition: { + var fd = metadata.GetFieldDefinition((FieldDefinitionHandle)entity); + signature = fd.DecodeSignature(new DisassemblerSignatureProvider(module, output), new Metadata.GenericContext(fd.GetDeclaringType(), module)); + signature(ILNameSyntax.SignatureNoNamedTypeParameters); + output.Write(' '); + ((EntityHandle)fd.GetDeclaringType()).WriteTo(module, output, Metadata.GenericContext.Empty, ILNameSyntax.TypeName); + output.Write("::"); + output.WriteReference(module, entity, DisassemblerHelpers.Escape(metadata.GetString(fd.Name))); + break; + } + case HandleKind.MethodDefinition: { + var md = metadata.GetMethodDefinition((MethodDefinitionHandle)entity); + methodSignature = md.DecodeSignature(new DisassemblerSignatureProvider(module, output), new Metadata.GenericContext((MethodDefinitionHandle)entity, module)); + if (methodSignature.Header.HasExplicitThis) { + output.Write("instance explicit "); + } else if (methodSignature.Header.IsInstance) { + output.Write("instance "); + } + if (methodSignature.Header.CallingConvention == SignatureCallingConvention.VarArgs) { + output.Write("vararg "); + } + methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters); + output.Write(' '); + var declaringType = md.GetDeclaringType(); + if (!declaringType.IsNil) { + ((EntityHandle)declaringType).WriteTo(module, output, genericContext, ILNameSyntax.TypeName); + output.Write("::"); + } + bool isCompilerControlled = (md.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope; + if (isCompilerControlled) { + output.WriteReference(module, entity, DisassemblerHelpers.Escape(metadata.GetString(md.Name) + "$PST" + MetadataTokens.GetToken(entity).ToString("X8"))); + } else { + output.WriteReference(module, entity, DisassemblerHelpers.Escape(metadata.GetString(md.Name))); + } + var genericParameters = md.GetGenericParameters(); + if (genericParameters.Count > 0) { + output.Write('<'); + for (int i = 0; i < genericParameters.Count; i++) { + if (i > 0) + output.Write(", "); + var gp = metadata.GetGenericParameter(genericParameters[i]); + if ((gp.Attributes & GenericParameterAttributes.ReferenceTypeConstraint) == GenericParameterAttributes.ReferenceTypeConstraint) { + output.Write("class "); + } else if ((gp.Attributes & GenericParameterAttributes.NotNullableValueTypeConstraint) == GenericParameterAttributes.NotNullableValueTypeConstraint) { + output.Write("valuetype "); + } + if ((gp.Attributes & GenericParameterAttributes.DefaultConstructorConstraint) == GenericParameterAttributes.DefaultConstructorConstraint) { + output.Write(".ctor "); + } + var constraints = gp.GetConstraints(); + if (constraints.Count > 0) { + output.Write('('); + for (int j = 0; j < constraints.Count; j++) { + if (j > 0) + output.Write(", "); + var constraint = metadata.GetGenericParameterConstraint(constraints[j]); + constraint.Type.WriteTo(module, output, new Metadata.GenericContext((MethodDefinitionHandle)entity, module), ILNameSyntax.TypeName); + } + output.Write(") "); + } + if ((gp.Attributes & GenericParameterAttributes.Contravariant) == GenericParameterAttributes.Contravariant) { + output.Write('-'); + } else if ((gp.Attributes & GenericParameterAttributes.Covariant) == GenericParameterAttributes.Covariant) { + output.Write('+'); + } + output.Write(DisassemblerHelpers.Escape(metadata.GetString(gp.Name))); + } + output.Write('>'); + } + output.Write("("); + for (int i = 0; i < methodSignature.ParameterTypes.Length; ++i) { + if (i > 0) + output.Write(", "); + methodSignature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters); + } + output.Write(")"); + break; + } + case HandleKind.MemberReference: + var mr = metadata.GetMemberReference((MemberReferenceHandle)entity); + memberName = metadata.GetString(mr.Name); + switch (mr.GetKind()) { + case MemberReferenceKind.Method: + methodSignature = mr.DecodeMethodSignature(new DisassemblerSignatureProvider(module, output), genericContext); + if (methodSignature.Header.HasExplicitThis) { + output.Write("instance explicit "); + } else if (methodSignature.Header.IsInstance) { + output.Write("instance "); + } + if (methodSignature.Header.CallingConvention == SignatureCallingConvention.VarArgs) { + output.Write("vararg "); + } + methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters); + output.Write(' '); + WriteParent(output, module, metadata, mr.Parent, genericContext, syntax); + output.Write("::"); + output.WriteReference(module, entity, DisassemblerHelpers.Escape(memberName)); + output.Write("("); + for (int i = 0; i < methodSignature.ParameterTypes.Length; ++i) { + if (i > 0) + output.Write(", "); + if (i == methodSignature.RequiredParameterCount) + output.Write("..., "); + methodSignature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters); + } + output.Write(")"); + break; + case MemberReferenceKind.Field: + var fieldSignature = mr.DecodeFieldSignature(new DisassemblerSignatureProvider(module, output), genericContext); + fieldSignature(ILNameSyntax.SignatureNoNamedTypeParameters); + output.Write(' '); + WriteParent(output, module, metadata, mr.Parent, genericContext, syntax); + output.Write("::"); + output.WriteReference(module, entity, DisassemblerHelpers.Escape(memberName)); + break; + } + break; + case HandleKind.MethodSpecification: + var ms = metadata.GetMethodSpecification((MethodSpecificationHandle)entity); + var substitution = ms.DecodeSignature(new DisassemblerSignatureProvider(module, output), genericContext); + switch (ms.Method.Kind) { + case HandleKind.MethodDefinition: + var methodDefinition = metadata.GetMethodDefinition((MethodDefinitionHandle)ms.Method); + var methodName = metadata.GetString(methodDefinition.Name); + methodSignature = methodDefinition.DecodeSignature(new DisassemblerSignatureProvider(module, output), genericContext); + if (methodSignature.Header.HasExplicitThis) { + output.Write("instance explicit "); + } else if (methodSignature.Header.IsInstance) { + output.Write("instance "); + } + if (methodSignature.Header.CallingConvention == SignatureCallingConvention.VarArgs) { + output.Write("vararg "); + } + methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters); + output.Write(' '); + var declaringType = methodDefinition.GetDeclaringType(); + if (!declaringType.IsNil) { + ((EntityHandle)declaringType).WriteTo(module, output, genericContext, ILNameSyntax.TypeName); + output.Write("::"); + } + bool isCompilerControlled = (methodDefinition.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope; + if (isCompilerControlled) { + output.Write(DisassemblerHelpers.Escape(methodName + "$PST" + MetadataTokens.GetToken(ms.Method).ToString("X8"))); + } else { + output.Write(DisassemblerHelpers.Escape(methodName)); + } + output.Write('<'); + for (int i = 0; i < substitution.Length; i++) { + if (i > 0) + output.Write(", "); + substitution[i](syntax); + } + output.Write('>'); + output.Write("("); + for (int i = 0; i < methodSignature.ParameterTypes.Length; ++i) { + if (i > 0) + output.Write(", "); + methodSignature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters); + } + output.Write(")"); + break; + case HandleKind.MemberReference: + var memberReference = metadata.GetMemberReference((MemberReferenceHandle)ms.Method); + memberName = metadata.GetString(memberReference.Name); + methodSignature = memberReference.DecodeMethodSignature(new DisassemblerSignatureProvider(module, output), genericContext); + if (methodSignature.Header.HasExplicitThis) { + output.Write("instance explicit "); + } else if (methodSignature.Header.IsInstance) { + output.Write("instance "); + } + if (methodSignature.Header.CallingConvention == SignatureCallingConvention.VarArgs) { + output.Write("vararg "); + } + methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters); + output.Write(' '); + WriteParent(output, module, metadata, memberReference.Parent, genericContext, syntax); + output.Write("::"); + output.Write(DisassemblerHelpers.Escape(memberName)); + output.Write('<'); + for (int i = 0; i < substitution.Length; i++) { + if (i > 0) + output.Write(", "); + substitution[i](syntax); + } + output.Write('>'); + output.Write("("); + for (int i = 0; i < methodSignature.ParameterTypes.Length; ++i) { + if (i > 0) + output.Write(", "); + methodSignature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters); + } + output.Write(")"); + break; + } + break; + case HandleKind.StandaloneSignature: + var standaloneSig = metadata.GetStandaloneSignature((StandaloneSignatureHandle)entity); + switch (standaloneSig.GetKind()) { + case StandaloneSignatureKind.Method: + var methodSig = standaloneSig.DecodeMethodSignature(new DisassemblerSignatureProvider(module, output), genericContext); + methodSig.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters); + output.Write('('); + for (int i = 0; i < methodSig.ParameterTypes.Length; i++) { + if (i > 0) + output.Write(", "); + methodSig.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters); + } + output.Write(')'); + break; + case StandaloneSignatureKind.LocalVariables: + default: + output.Write($"@{MetadataTokens.GetToken(entity):X8} /* signature {standaloneSig.GetKind()} */"); + break; + } + break; + default: + output.Write($"@{MetadataTokens.GetToken(entity):X8}"); + break; + } + } + + static void WriteParent(ITextOutput output, PEFile module, MetadataReader metadata, EntityHandle parentHandle, Metadata.GenericContext genericContext, ILNameSyntax syntax) + { + switch (parentHandle.Kind) { + case HandleKind.MethodDefinition: + var methodDef = metadata.GetMethodDefinition((MethodDefinitionHandle)parentHandle); + ((EntityHandle)methodDef.GetDeclaringType()).WriteTo(module, output, genericContext, syntax); + break; + case HandleKind.ModuleReference: + output.Write('['); + var moduleRef = metadata.GetModuleReference((ModuleReferenceHandle)parentHandle); + output.Write(metadata.GetString(moduleRef.Name)); + output.Write(']'); + break; + case HandleKind.TypeDefinition: + case HandleKind.TypeReference: + case HandleKind.TypeSpecification: + parentHandle.WriteTo(module, output, genericContext, syntax); + break; + } + } + } } diff --git a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs index 25d10dcb3..f67a43bf8 100644 --- a/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs +++ b/ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs @@ -106,18 +106,6 @@ namespace ICSharpCode.Decompiler.Metadata } } - public static bool IsConstructor(this SRM.MethodDefinition methodDefinition, MetadataReader reader) - { - string name = reader.GetString(methodDefinition.Name); - return (methodDefinition.Attributes & (MethodAttributes.RTSpecialName | MethodAttributes.SpecialName)) != 0 - && (name == ".cctor" || name == ".ctor"); - } - - public static string GetDefaultMemberName(this TypeDefinitionHandle type, MetadataReader reader) - { - return type.GetDefaultMemberName(reader, out var attr); - } - internal static readonly TypeProvider minimalCorlibTypeProvider = new TypeProvider(new SimpleCompilation(MinimalCorlib.Instance)); @@ -129,48 +117,6 @@ namespace ICSharpCode.Decompiler.Metadata get => minimalCorlibTypeProvider; } - public static string GetDefaultMemberName(this TypeDefinitionHandle type, MetadataReader reader, out CustomAttributeHandle defaultMemberAttribute) - { - var td = reader.GetTypeDefinition(type); - - foreach (var h in td.GetCustomAttributes()) { - var ca = reader.GetCustomAttribute(h); - if (ca.IsKnownAttribute(reader, KnownAttribute.DefaultMember)) { - var decodedValues = ca.DecodeValue(minimalCorlibTypeProvider); - if (decodedValues.FixedArguments.Length == 1 && decodedValues.FixedArguments[0].Value is string value) { - defaultMemberAttribute = h; - return value; - } - } - } - - defaultMemberAttribute = default(CustomAttributeHandle); - return null; - } - - public static bool HasOverrides(this MethodDefinitionHandle handle, MetadataReader reader) - { - for (int row = 1; row <= reader.GetTableRowCount(TableIndex.MethodImpl); row++) { - var impl = reader.GetMethodImplementation(MetadataTokens.MethodImplementationHandle(row)); - if (impl.MethodBody == handle) return true; - } - return false; - } - - public static bool HasParameters(this PropertyDefinitionHandle handle, MetadataReader reader) - { - var a = reader.GetPropertyDefinition(handle).GetAccessors(); - if (!a.Getter.IsNil) { - var m = reader.GetMethodDefinition(a.Getter); - return m.GetParameters().Count > 0; - } - if (!a.Setter.IsNil) { - var m = reader.GetMethodDefinition(a.Setter); - return m.GetParameters().Count > 1; - } - return false; - } - public static PrimitiveTypeCode ToPrimitiveTypeCode(this KnownTypeCode typeCode) { switch (typeCode) { @@ -259,68 +205,6 @@ namespace ICSharpCode.Decompiler.Metadata } } - public static bool IsSmallReference(this MetadataReader reader, TableIndex table) - { - // TODO detect whether #JTD is present (EnC) - return reader.GetTableRowCount(table) <= ushort.MaxValue; - } - - public static int GetReferenceSize(this MetadataReader reader, TableIndex table) - { - return IsSmallReference(reader, table) ? 2 : 4; - } - - public static unsafe (int startRow, int endRow) BinarySearchRange(this MetadataReader reader, TableIndex table, int valueOffset, uint referenceValue, bool small) - { - int offset = reader.GetTableMetadataOffset(table); - int rowSize = reader.GetTableRowSize(table); - int rowCount = reader.GetTableRowCount(table); - int tableLength = rowSize * rowCount; - byte* startPointer = reader.MetadataPointer; - - int result = BinarySearch(); - if (result == -1) - return (-1, -1); - - int start = result; - - while (start > 0 && GetValue(start - 1) == referenceValue) - start--; - - int end = result; - - while (end + 1 < tableLength && GetValue(end + 1) == referenceValue) - end++; - - return (start, end); - - uint GetValue(int row) - { - if (small) - return *(ushort*)(startPointer + offset + row * rowSize + valueOffset); - else - return *(uint*)(startPointer + offset + row * rowSize + valueOffset); - } - - int BinarySearch() - { - int startRow = 0; - int endRow = rowCount - 1; - while (startRow <= endRow) { - int row = (startRow + endRow) / 2; - uint currentValue = GetValue(row); - if (referenceValue > currentValue) { - startRow = row + 1; - } else if (referenceValue < currentValue) { - endRow = row - 1; - } else { - return row; - } - } - return -1; - } - } - public static AssemblyDefinition? GetAssemblyDefinition(this PEReader reader) { var metadata = reader.GetMetadataReader(); @@ -329,21 +213,6 @@ namespace ICSharpCode.Decompiler.Metadata 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); - } - - public static IEnumerable GetModuleReferences(this MetadataReader metadata) { var rowCount = metadata.GetTableRowCount(TableIndex.ModuleRef); diff --git a/ICSharpCode.Decompiler/SRMExtensions.cs b/ICSharpCode.Decompiler/SRMExtensions.cs index d8dec2250..75981ca76 100644 --- a/ICSharpCode.Decompiler/SRMExtensions.cs +++ b/ICSharpCode.Decompiler/SRMExtensions.cs @@ -84,14 +84,6 @@ namespace ICSharpCode.Decompiler var baseType = typeDefinition.BaseType; return !baseType.IsNil && baseType.IsKnownType(reader, KnownTypeCode.MulticastDelegate); } - - public static bool IsExtensionMethod(this MethodDefinition methodDefinition, MetadataReader reader) - { - if (methodDefinition.HasFlag(MethodAttributes.Static)) { - return methodDefinition.GetCustomAttributes().HasKnownAttribute(reader, KnownAttribute.Extension); - } - return false; - } public static bool HasBody(this MethodDefinition methodDefinition) { diff --git a/ICSharpCode.Decompiler/SRMHacks.cs b/ICSharpCode.Decompiler/SRMHacks.cs index f5370a369..c2ba77b25 100644 --- a/ICSharpCode.Decompiler/SRMHacks.cs +++ b/ICSharpCode.Decompiler/SRMHacks.cs @@ -13,25 +13,6 @@ namespace ICSharpCode.Decompiler { public static partial class SRMExtensions { - public static unsafe MethodSemanticsAttributes GetMethodSemanticsAttributes(this MethodDefinitionHandle handle, MetadataReader reader) - { - byte* startPointer = reader.MetadataPointer; - int offset = reader.GetTableMetadataOffset(TableIndex.MethodSemantics); - int rowSize = reader.GetTableRowSize(TableIndex.MethodSemantics); - int rowCount = reader.GetTableRowCount(TableIndex.MethodSemantics); - var small = reader.IsSmallReference(TableIndex.MethodDef); - - int methodRowNo = reader.GetRowNumber(handle); - for (int row = rowCount - 1; row >= 0; row--) { - byte* ptr = startPointer + offset + rowSize * row; - uint rowNo = small ? *(ushort*)(ptr + 2) : *(uint*)(ptr + 2); - if (methodRowNo == rowNo) { - return (MethodSemanticsAttributes)(*(ushort*)ptr); - } - } - return 0; - } - public static ImmutableArray GetMethodImplementations(this MethodDefinitionHandle handle, MetadataReader reader) { var resultBuilder = ImmutableArray.CreateBuilder(); @@ -46,30 +27,5 @@ namespace ICSharpCode.Decompiler return resultBuilder.ToImmutable(); } - - /* - internal static unsafe ImmutableArray<(MethodSemanticsAttributes Kind, MethodDefinition Method)> GetAccessors(PEFile module, uint encodedTag) - { - var reader = Module.Metadata; - byte* startPointer = reader.MetadataPointer; - int offset = reader.GetTableMetadataOffset(TableIndex.MethodSemantics); - - var methodDefRefSize = reader.GetReferenceSize(TableIndex.MethodDef); - (int startRow, int endRow) = reader.BinarySearchRange(TableIndex.MethodSemantics, 2 + methodDefRefSize, encodedTag, reader.IsSmallReference(TableIndex.MethodSemantics)); - if (startRow == -1) - return ImmutableArray<(MethodSemanticsAttributes Kind, MethodDefinition Method)>.Empty; - var methods = new(MethodSemanticsAttributes Kind, MethodDefinition Method)[endRow - startRow + 1]; - int rowSize = reader.GetTableRowSize(TableIndex.MethodSemantics); - for (int row = startRow; row <= endRow; row++) { - int rowOffset = row * rowSize; - byte* ptr = startPointer + offset + rowOffset; - var kind = (MethodSemanticsAttributes)(*(ushort*)ptr); - uint rowNo = methodDefRefSize == 2 ? *(ushort*)(ptr + 2) : *(uint*)(ptr + 2); - var handle = MetadataTokens.MethodDefinitionHandle((int)rowNo); - methods[row - startRow] = (kind, new MethodDefinition(module, handle)); - } - return methods.ToImmutableArray(); - } - */ } }