Browse Source

Fix bugs when dealing with pinned local vars and varargs methods

pull/1198/head
Siegfried Pammer 8 years ago
parent
commit
fb41cfe4f8
  1. 48
      ICSharpCode.Decompiler/IL/ILReader.cs
  2. 90
      ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
  3. 3
      ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs
  4. 22
      ICSharpCode.Decompiler/TypeSystem/Implementation/TypeSpecification.cs
  5. 20
      ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs
  6. 5
      ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs

48
ICSharpCode.Decompiler/IL/ILReader.cs

@ -28,6 +28,7 @@ using ICSharpCode.Decompiler.TypeSystem; @@ -28,6 +28,7 @@ using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
using ArrayType = ICSharpCode.Decompiler.TypeSystem.ArrayType;
using ByReferenceType = ICSharpCode.Decompiler.TypeSystem.ByReferenceType;
using PinnedType = ICSharpCode.Decompiler.TypeSystem.Implementation.PinnedType;
using ICSharpCode.Decompiler.Disassembler;
using System.Reflection.Metadata.Ecma335;
@ -53,7 +54,6 @@ namespace ICSharpCode.Decompiler.IL @@ -53,7 +54,6 @@ namespace ICSharpCode.Decompiler.IL
IMethod method;
MethodBodyBlock body;
Metadata.IDebugInfoProvider debugInfo;
ITypeResolveContext resolveContext;
MethodSignature<ITypeReference> methodSignature;
StackType methodReturnStackType;
BlobReader reader;
@ -86,8 +86,7 @@ namespace ICSharpCode.Decompiler.IL @@ -86,8 +86,7 @@ namespace ICSharpCode.Decompiler.IL
this.currentStack = ImmutableStack<ILVariable>.Empty;
this.unionFind = new UnionFind<ILVariable>();
this.stackMismatchPairs = new List<(ILVariable, ILVariable)>();
this.resolveContext = new SimpleTypeResolveContext(this.method);
this.methodReturnStackType = TypeSystem.Implementation.DynamicAwareTypeReference.Create(methodSignature.ReturnType, methodDefinition.GetCustomAttributes(), metadata).Resolve(resolveContext).GetStackType();
this.methodReturnStackType = typeSystem.ResolveFromSignature(TypeSystem.Implementation.DynamicAwareTypeReference.Create(methodSignature.ReturnType, methodDefinition.GetCustomAttributes(), metadata)).GetStackType();
InitParameterVariables();
localVariables = InitLocalVariables();
if (body.LocalVariablesInitialized) {
@ -140,7 +139,12 @@ namespace ICSharpCode.Decompiler.IL @@ -140,7 +139,12 @@ namespace ICSharpCode.Decompiler.IL
void InitParameterVariables()
{
parameterVariables = new ILVariable[GetPopCount(OpCode.Call, method)];
int popCount = method.Parameters.Count;
if (!method.IsStatic)
popCount++;
if (method.Parameters.LastOrDefault()?.Type == SpecialType.ArgList)
popCount--;
parameterVariables = new ILVariable[popCount];
int paramIndex = 0; int offset = 0;
if (methodSignature.Header.IsInstance) {
offset = 1;
@ -154,10 +158,17 @@ namespace ICSharpCode.Decompiler.IL @@ -154,10 +158,17 @@ namespace ICSharpCode.Decompiler.IL
Debug.Assert(paramIndex == parameterVariables.Length);
}
ILVariable CreateILVariable(int index, ITypeReference type)
ILVariable CreateILVariable(int index, ITypeReference typeRef)
{
VariableKind kind = IsPinned(type) ? VariableKind.PinnedLocal : VariableKind.Local;
ILVariable ilVar = new ILVariable(kind, type.Resolve(resolveContext), index);
IType type = typeSystem.ResolveFromSignature(typeRef);
VariableKind kind;
if (type is PinnedType pinned) {
kind = VariableKind.PinnedLocal;
type = pinned.ElementType;
} else {
kind = VariableKind.Local;
}
ILVariable ilVar = new ILVariable(kind, type, index);
if (!UseDebugSymbols || debugInfo == null || !debugInfo.TryGetName((MethodDefinitionHandle)method.MetadataToken, index, out string name)) {
ilVar.Name = "V_" + index;
ilVar.HasGeneratedName = true;
@ -170,14 +181,13 @@ namespace ICSharpCode.Decompiler.IL @@ -170,14 +181,13 @@ namespace ICSharpCode.Decompiler.IL
return ilVar;
}
bool IsPinned(ITypeReference type)
{
return type is TypeSystem.Implementation.PinnedTypeReference;
}
ILVariable CreateILVariable(int index, ITypeReference typeReference, string name)
{
IType parameterType = typeReference.Resolve(resolveContext);
IType parameterType = typeSystem.ResolveFromSignature(typeReference);
ITypeDefinition def = parameterType.GetDefinition();
if (def != null && index < 0 && def.IsReferenceType == false) {
parameterType = new ByReferenceType(parameterType);
}
Debug.Assert(!parameterType.IsUnbound());
if (parameterType.IsUnbound()) {
// parameter types should not be unbound, the only known cause for these is a Cecil bug:
@ -1288,12 +1298,12 @@ namespace ICSharpCode.Decompiler.IL @@ -1288,12 +1298,12 @@ namespace ICSharpCode.Decompiler.IL
var parameterTypes = new IType[signature.ParameterTypes.Length];
var arguments = new ILInstruction[parameterTypes.Length];
for (int i = signature.ParameterTypes.Length - 1; i >= 0; i--) {
parameterTypes[i] = signature.ParameterTypes[i].Resolve(resolveContext);
parameterTypes[i] = typeSystem.ResolveFromSignature(signature.ParameterTypes[i]);
arguments[i] = Pop(parameterTypes[i].GetStackType());
}
var call = new CallIndirect(
signature.Header.CallingConvention,
signature.ReturnType.Resolve(resolveContext),
typeSystem.ResolveFromSignature(signature.ReturnType),
parameterTypes.ToImmutableArray(),
arguments,
functionPointer
@ -1304,14 +1314,6 @@ namespace ICSharpCode.Decompiler.IL @@ -1304,14 +1314,6 @@ namespace ICSharpCode.Decompiler.IL
return call;
}
static int GetPopCount(OpCode callCode, IMethod method)
{
int popCount = method.Parameters.Count;
if (callCode != OpCode.NewObj && !method.IsStatic)
popCount++;
return popCount;
}
ILInstruction Comparison(ComparisonKind kind, bool un = false)
{
var right = Pop();

90
ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

@ -98,46 +98,10 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -98,46 +98,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
entityDict[entity] = mr;
}
/*
Metadata.IMetadataEntity GetMetadata(IUnresolvedEntity member)
public IType ResolveFromSignature(ITypeReference typeReference)
{
if (member == null)
return null;
lock (entityDict) {
if (entityDict.TryGetValue(member, out var mr))
return mr;
return null;
}
}
/// <summary>
/// Retrieves the Cecil member definition for the specified member.
/// </summary>
/// <remarks>
/// Returns null if the member is not defined in the module being decompiled.
/// </remarks>
public Metadata.IMetadataEntity GetMetadata(IMember member)
{
if (member == null)
return null;
return GetMetadata(member.UnresolvedMember);
}
/// <summary>
/// Retrieves the Cecil type definition.
/// </summary>
/// <remarks>
/// Returns null if the type is not defined in the module being decompiled.
/// </remarks>
public Metadata.TypeDefinition GetMetadata(ITypeDefinition typeDefinition)
{
if (typeDefinition == null)
return default;
return (Metadata.TypeDefinition)GetMetadata(typeDefinition.Parts[0]);
return typeReference.Resolve(context);
}
*/
public IMember ResolveAsMember(SRM.EntityHandle memberReference)
{
@ -208,21 +172,13 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -208,21 +172,13 @@ namespace ICSharpCode.Decompiler.TypeSystem
var memberRef = metadata.GetMemberReference((SRM.MemberReferenceHandle)fieldReference);
Debug.Assert(memberRef.GetKind() == SRM.MemberReferenceKind.Field);
declaringType = ResolveAsType(memberRef.Parent);
switch (memberRef.Parent.Kind) {
case SRM.HandleKind.TypeReference:
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();
}
field = FindNonGenericField(metadata, memberRef, declaringType);
break;
default:
throw new NotSupportedException();
}
if (declaringType.TypeArguments.Count > 0) {
field = (IField)field.Specialize(new TypeParameterSubstitution(declaringType.TypeArguments, null));
}
fieldLookupCache.Add(fieldReference, field);
}
@ -246,6 +202,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -246,6 +202,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
IField CreateFakeField(IType declaringType, string name, ITypeReference returnType)
{
Debug.Assert(false, $"Creating fake field for {name}!");
var f = new DefaultUnresolvedField();
f.Name = name;
f.ReturnType = returnType;
@ -281,13 +238,25 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -281,13 +238,25 @@ namespace ICSharpCode.Decompiler.TypeSystem
IType declaringType;
IReadOnlyList<IType> classTypeArguments = null;
IReadOnlyList<IType> methodTypeArguments = null;
SRM.MethodSignature<ITypeReference>? signature = null;
if (!methodLookupCache.TryGetValue(methodReference, out method)) {
var metadata = moduleDefinition.GetMetadataReader();
switch (methodReference.Kind) {
case SRM.HandleKind.MethodDefinition:
case SRM.HandleKind.MemberReference:
var methodDef = metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)methodReference);
signature = methodDef.DecodeSignature(TypeReferenceSignatureDecoder.Instance, default);
method = FindNonGenericMethod(metadata, methodReference, out declaringType);
break;
case SRM.HandleKind.MemberReference:
var memberRef = metadata.GetMemberReference((SRM.MemberReferenceHandle)methodReference);
Debug.Assert(memberRef.GetKind() == SRM.MemberReferenceKind.Method);
signature = memberRef.DecodeMethodSignature(TypeReferenceSignatureDecoder.Instance, default);
var elementMethod = methodReference;
if (memberRef.Parent.Kind == SRM.HandleKind.MethodDefinition) {
elementMethod = (SRM.MethodDefinitionHandle)memberRef.Parent;
}
method = FindNonGenericMethod(metadata, elementMethod, out declaringType);
break;
case SRM.HandleKind.MethodSpecification:
var methodSpec = metadata.GetMethodSpecification((SRM.MethodSpecificationHandle)methodReference);
method = FindNonGenericMethod(metadata, methodSpec.Method, out declaringType);
@ -299,6 +268,9 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -299,6 +268,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
default:
throw new NotSupportedException();
}
if (signature?.Header.CallingConvention == SRM.SignatureCallingConvention.VarArgs) {
method = new VarArgInstanceMethod(method, signature.Value.ParameterTypes.Skip(signature.Value.RequiredParameterCount).Select(p => p.Resolve(context)));
}
if (declaringType.TypeArguments.Count > 0) {
classTypeArguments = declaringType.TypeArguments.ToList();
}
@ -338,8 +310,15 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -338,8 +310,15 @@ namespace ICSharpCode.Decompiler.TypeSystem
case SRM.HandleKind.MemberReference:
var memberRef = metadata.GetMemberReference((SRM.MemberReferenceHandle)methodReference);
Debug.Assert(memberRef.GetKind() == SRM.MemberReferenceKind.Method);
declaringType = ResolveAsType(memberRef.Parent);
// TODO : Support other handles
switch (memberRef.Parent.Kind) {
case SRM.HandleKind.MethodDefinition:
FindNonGenericMethod(metadata, memberRef.Parent, out declaringType);
break;
default:
declaringType = ResolveAsType(memberRef.Parent);
break;
}
declaringTypeDefinition = declaringType.GetDefinition();
var signature = memberRef.DecodeMethodSignature(TypeReferenceSignatureDecoder.Instance, default);
if (declaringTypeDefinition == null) {
@ -407,7 +386,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -407,7 +386,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary>
IMethod CreateFakeMethod(IType declaringType, string name, SRM.MethodSignature<ITypeReference> signature)
{
Debug.Assert(false, $"Creating fake method for {name}!");
Debug.Assert(declaringType is ArrayType, $"Creating fake method for {name}!");
var m = new DefaultUnresolvedMethod();
if (name == ".ctor" || name == ".cctor")
m.SymbolKind = SymbolKind.Constructor;
@ -416,7 +395,6 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -416,7 +395,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
m.ReturnType = signature.ReturnType;
m.IsStatic = !signature.Header.IsInstance;
ITypeReference declaringTypeReference;
lock (typeReferenceCecilLoader) {
var metadata = moduleDefinition.GetMetadataReader();
for (int i = 0; i < signature.GenericParameterCount; i++) {

3
ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs

@ -27,7 +27,8 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -27,7 +27,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
public interface IDecompilerTypeSystem
{
ICompilation Compilation { get; }
IType ResolveFromSignature(ITypeReference typeReference);
IType ResolveAsType(EntityHandle typeReference);
IField ResolveAsField(EntityHandle fieldReference);
IMethod ResolveAsMethod(EntityHandle methodReference);

22
ICSharpCode.Decompiler/TypeSystem/Implementation/TypeSpecification.cs

@ -189,6 +189,26 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -189,6 +189,26 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
}
}
sealed class TypeDefTokenTypeReference : ITypeReference
{
readonly SRM.EntityHandle token;
public TypeDefTokenTypeReference(SRM.EntityHandle token)
{
if (token.Kind != SRM.HandleKind.TypeDefinition)
throw new ArgumentException(nameof(token), "must be TypeDef token");
this.token = token;
}
public IType Resolve(ITypeResolveContext context)
{
ITypeDefinition td = context.CurrentAssembly.ResolveTypeDefToken(token);
if (td != null)
return td;
return SpecialType.UnknownType;
}
}
class TypeReferenceSignatureDecoder : SRM.ISignatureTypeProvider<ITypeReference, Unit>
{
public static readonly TypeReferenceSignatureDecoder Instance = new TypeReferenceSignatureDecoder();
@ -252,7 +272,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -252,7 +272,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public ITypeReference GetTypeFromDefinition(SRM.MetadataReader reader, SRM.TypeDefinitionHandle handle, byte rawTypeKind)
{
return new GetClassTypeReference(handle.GetFullTypeName(reader), DefaultAssemblyReference.CurrentAssembly);
return new TypeDefTokenTypeReference(handle);
}
public ITypeReference GetTypeFromReference(SRM.MetadataReader reader, SRM.TypeReferenceHandle handle, byte rawTypeKind)

20
ICSharpCode.Decompiler/TypeSystem/MetadataLoader.cs

@ -313,26 +313,6 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -313,26 +313,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
throw new NotSupportedException();
}
}
sealed class TypeDefTokenTypeReference : ITypeReference
{
readonly EntityHandle token;
public TypeDefTokenTypeReference(EntityHandle token)
{
if (token.Kind != HandleKind.TypeDefinition)
throw new ArgumentException(nameof(token), "must be TypeDef token");
this.token = token;
}
public IType Resolve(ITypeResolveContext context)
{
ITypeDefinition td = context.CurrentAssembly.ResolveTypeDefToken(token);
if (td != null)
return td;
return SpecialType.UnknownType;
}
}
#endregion
#region Read Attributes

5
ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs

@ -53,6 +53,11 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -53,6 +53,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
get { return substitution; }
}
public IType ResolveFromSignature(ITypeReference typeReference)
{
return context.ResolveFromSignature(typeReference).AcceptVisitor(substitution);
}
public IType ResolveAsType(System.Reflection.Metadata.EntityHandle typeReference)
{
return context.ResolveAsType(typeReference).AcceptVisitor(substitution);

Loading…
Cancel
Save