Browse Source

Improve on #1085 by setting UnknownType.IsReferenceType in more cases.

pull/1108/head
Daniel Grunwald 8 years ago
parent
commit
0e9a163345
  1. 12
      ICSharpCode.Decompiler/IL/ILReader.cs
  2. 39
      ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
  3. 2
      ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs
  4. 4
      ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs

12
ICSharpCode.Decompiler/IL/ILReader.cs

@ -78,7 +78,7 @@ namespace ICSharpCode.Decompiler.IL
this.currentStack = ImmutableStack<ILVariable>.Empty; this.currentStack = ImmutableStack<ILVariable>.Empty;
this.unionFind = new UnionFind<ILVariable>(); this.unionFind = new UnionFind<ILVariable>();
this.stackMismatchPairs = new List<(ILVariable, ILVariable)>(); this.stackMismatchPairs = new List<(ILVariable, ILVariable)>();
this.methodReturnStackType = typeSystem.Resolve(body.Method.ReturnType).GetStackType(); this.methodReturnStackType = typeSystem.Resolve(body.Method.ReturnType, isFromSignature: true).GetStackType();
InitParameterVariables(); InitParameterVariables();
this.localVariables = body.Variables.SelectArray(CreateILVariable); this.localVariables = body.Variables.SelectArray(CreateILVariable);
if (body.InitLocals) { if (body.InitLocals) {
@ -130,7 +130,7 @@ namespace ICSharpCode.Decompiler.IL
ILVariable CreateILVariable(Cil.VariableDefinition v) ILVariable CreateILVariable(Cil.VariableDefinition v)
{ {
VariableKind kind = IsPinned(v.VariableType) ? VariableKind.PinnedLocal : VariableKind.Local; VariableKind kind = IsPinned(v.VariableType) ? VariableKind.PinnedLocal : VariableKind.Local;
ILVariable ilVar = new ILVariable(kind, typeSystem.Resolve(v.VariableType), v.Index); ILVariable ilVar = new ILVariable(kind, typeSystem.Resolve(v.VariableType, isFromSignature: true), v.Index);
if (!UseDebugSymbols || debugInfo == null || !debugInfo.TryGetName(v, out string name)) { if (!UseDebugSymbols || debugInfo == null || !debugInfo.TryGetName(v, out string name)) {
ilVar.Name = "V_" + v.Index; ilVar.Name = "V_" + v.Index;
ilVar.HasGeneratedName = true; ilVar.HasGeneratedName = true;
@ -164,10 +164,10 @@ namespace ICSharpCode.Decompiler.IL
parameterType = new ByReferenceType(parameterType); parameterType = new ByReferenceType(parameterType);
} }
} else { } else {
parameterType = typeSystem.Resolve(p.ParameterType); parameterType = typeSystem.Resolve(p.ParameterType, isFromSignature: true);
} }
} else { } else {
parameterType = typeSystem.Resolve(p.ParameterType); parameterType = typeSystem.Resolve(p.ParameterType, isFromSignature: true);
} }
Debug.Assert(!parameterType.IsUnbound()); Debug.Assert(!parameterType.IsUnbound());
if (parameterType.IsUnbound()) { if (parameterType.IsUnbound()) {
@ -1283,12 +1283,12 @@ namespace ICSharpCode.Decompiler.IL
var parameterTypes = new IType[signature.Parameters.Count]; var parameterTypes = new IType[signature.Parameters.Count];
var arguments = new ILInstruction[parameterTypes.Length]; var arguments = new ILInstruction[parameterTypes.Length];
for (int i = signature.Parameters.Count - 1; i >= 0; i--) { for (int i = signature.Parameters.Count - 1; i >= 0; i--) {
parameterTypes[i] = typeSystem.Resolve(signature.Parameters[i].ParameterType); parameterTypes[i] = typeSystem.Resolve(signature.Parameters[i].ParameterType, isFromSignature: true);
arguments[i] = Pop(parameterTypes[i].GetStackType()); arguments[i] = Pop(parameterTypes[i].GetStackType());
} }
var call = new CallIndirect( var call = new CallIndirect(
signature.CallingConvention, signature.CallingConvention,
typeSystem.Resolve(signature.ReturnType), typeSystem.Resolve(signature.ReturnType, isFromSignature: true),
parameterTypes.ToImmutableArray(), parameterTypes.ToImmutableArray(),
arguments, arguments,
functionPointer functionPointer

39
ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

@ -136,7 +136,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
#region Resolve Type #region Resolve Type
public IType Resolve(TypeReference typeReference) public IType Resolve(TypeReference typeReference, bool isFromSignature = false)
{ {
if (typeReference == null) if (typeReference == null)
return SpecialType.UnknownType; return SpecialType.UnknownType;
@ -144,15 +144,22 @@ namespace ICSharpCode.Decompiler.TypeSystem
// But PinnedType can be nested within modopt, so we'll also skip those. // But PinnedType can be nested within modopt, so we'll also skip those.
while (typeReference is OptionalModifierType || typeReference is RequiredModifierType) { while (typeReference is OptionalModifierType || typeReference is RequiredModifierType) {
typeReference = ((TypeSpecification)typeReference).ElementType; typeReference = ((TypeSpecification)typeReference).ElementType;
isFromSignature = true;
} }
if (typeReference is SentinelType || typeReference is PinnedType) { if (typeReference is SentinelType || typeReference is PinnedType) {
typeReference = ((TypeSpecification)typeReference).ElementType; typeReference = ((TypeSpecification)typeReference).ElementType;
isFromSignature = true;
} }
ITypeReference typeRef; ITypeReference typeRef;
lock (typeReferenceCecilLoader) lock (typeReferenceCecilLoader)
typeRef = typeReferenceCecilLoader.ReadTypeReference(typeReference); typeRef = typeReferenceCecilLoader.ReadTypeReference(typeReference, isFromSignature: isFromSignature);
return typeRef.Resolve(context); return typeRef.Resolve(context);
} }
IType ResolveInSignature(TypeReference typeReference)
{
return Resolve(typeReference, isFromSignature: true);
}
#endregion #endregion
#region Resolve Field #region Resolve Field
@ -166,7 +173,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
field = FindNonGenericField(fieldReference); field = FindNonGenericField(fieldReference);
if (fieldReference.DeclaringType.IsGenericInstance) { if (fieldReference.DeclaringType.IsGenericInstance) {
var git = (GenericInstanceType)fieldReference.DeclaringType; var git = (GenericInstanceType)fieldReference.DeclaringType;
var typeArguments = git.GenericArguments.SelectArray(Resolve); var typeArguments = git.GenericArguments.SelectArray(ResolveInSignature);
field = (IField)field.Specialize(new TypeParameterSubstitution(typeArguments, null)); field = (IField)field.Specialize(new TypeParameterSubstitution(typeArguments, null));
} }
fieldLookupCache.Add(fieldReference, field); fieldLookupCache.Add(fieldReference, field);
@ -226,18 +233,18 @@ namespace ICSharpCode.Decompiler.TypeSystem
if (methodReference.CallingConvention == MethodCallingConvention.VarArg) { if (methodReference.CallingConvention == MethodCallingConvention.VarArg) {
method = new VarArgInstanceMethod( method = new VarArgInstanceMethod(
method, method,
methodReference.Parameters.SkipWhile(p => !p.ParameterType.IsSentinel).Select(p => Resolve(p.ParameterType)) methodReference.Parameters.SkipWhile(p => !p.ParameterType.IsSentinel).Select(p => ResolveInSignature(p.ParameterType))
); );
} else if (methodReference.IsGenericInstance || methodReference.DeclaringType.IsGenericInstance) { } else if (methodReference.IsGenericInstance || methodReference.DeclaringType.IsGenericInstance) {
IReadOnlyList<IType> classTypeArguments = null; IReadOnlyList<IType> classTypeArguments = null;
IReadOnlyList<IType> methodTypeArguments = null; IReadOnlyList<IType> methodTypeArguments = null;
if (methodReference.IsGenericInstance) { if (methodReference.IsGenericInstance) {
var gim = ((GenericInstanceMethod)methodReference); var gim = ((GenericInstanceMethod)methodReference);
methodTypeArguments = gim.GenericArguments.SelectArray(Resolve); methodTypeArguments = gim.GenericArguments.SelectArray(ResolveInSignature);
} }
if (methodReference.DeclaringType.IsGenericInstance) { if (methodReference.DeclaringType.IsGenericInstance) {
var git = (GenericInstanceType)methodReference.DeclaringType; var git = (GenericInstanceType)methodReference.DeclaringType;
classTypeArguments = git.GenericArguments.SelectArray(Resolve); classTypeArguments = git.GenericArguments.SelectArray(ResolveInSignature);
} }
method = method.Specialize(new TypeParameterSubstitution(classTypeArguments, methodTypeArguments)); method = method.Specialize(new TypeParameterSubstitution(classTypeArguments, methodTypeArguments));
} }
@ -261,21 +268,23 @@ namespace ICSharpCode.Decompiler.TypeSystem
methods = typeDef.GetMethods(m => m.Name == methodReference.Name, GetMemberOptions.IgnoreInheritedMembers) methods = typeDef.GetMethods(m => m.Name == methodReference.Name, GetMemberOptions.IgnoreInheritedMembers)
.Concat(typeDef.GetAccessors(m => m.Name == methodReference.Name, GetMemberOptions.IgnoreInheritedMembers)); .Concat(typeDef.GetAccessors(m => m.Name == methodReference.Name, GetMemberOptions.IgnoreInheritedMembers));
} }
foreach (var method in methods) { if (methodReference.MetadataToken.TokenType == TokenType.Method) {
if (GetCecil(method) == methodReference) foreach (var method in methods) {
return method; if (method.MetadataToken == methodReference.MetadataToken)
return method;
}
} }
IType[] parameterTypes; IType[] parameterTypes;
if (methodReference.CallingConvention == MethodCallingConvention.VarArg) { if (methodReference.CallingConvention == MethodCallingConvention.VarArg) {
parameterTypes = methodReference.Parameters parameterTypes = methodReference.Parameters
.TakeWhile(p => !p.ParameterType.IsSentinel) .TakeWhile(p => !p.ParameterType.IsSentinel)
.Select(p => Resolve(p.ParameterType)) .Select(p => ResolveInSignature(p.ParameterType))
.Concat(new[] { SpecialType.ArgList }) .Concat(new[] { SpecialType.ArgList })
.ToArray(); .ToArray();
} else { } else {
parameterTypes = methodReference.Parameters.SelectArray(p => Resolve(p.ParameterType)); parameterTypes = methodReference.Parameters.SelectArray(p => ResolveInSignature(p.ParameterType));
} }
var returnType = Resolve(methodReference.ReturnType); var returnType = ResolveInSignature(methodReference.ReturnType);
foreach (var method in methods) { foreach (var method in methods) {
if (method.TypeParameters.Count != methodReference.GenericParameters.Count) if (method.TypeParameters.Count != methodReference.GenericParameters.Count)
continue; continue;
@ -362,7 +371,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
property = FindNonGenericProperty(propertyReference); property = FindNonGenericProperty(propertyReference);
if (propertyReference.DeclaringType.IsGenericInstance) { if (propertyReference.DeclaringType.IsGenericInstance) {
var git = (GenericInstanceType)propertyReference.DeclaringType; var git = (GenericInstanceType)propertyReference.DeclaringType;
var typeArguments = git.GenericArguments.SelectArray(Resolve); var typeArguments = git.GenericArguments.SelectArray(ResolveInSignature);
property = (IProperty)property.Specialize(new TypeParameterSubstitution(typeArguments, null)); property = (IProperty)property.Specialize(new TypeParameterSubstitution(typeArguments, null));
} }
propertyLookupCache.Add(propertyReference, property); propertyLookupCache.Add(propertyReference, property);
@ -376,7 +385,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
ITypeDefinition typeDef = Resolve(propertyReference.DeclaringType).GetDefinition(); ITypeDefinition typeDef = Resolve(propertyReference.DeclaringType).GetDefinition();
if (typeDef == null) if (typeDef == null)
return null; return null;
var parameterTypes = propertyReference.Parameters.SelectArray(p => Resolve(p.ParameterType)); var parameterTypes = propertyReference.Parameters.SelectArray(p => ResolveInSignature(p.ParameterType));
var returnType = Resolve(propertyReference.PropertyType); var returnType = Resolve(propertyReference.PropertyType);
foreach (IProperty property in typeDef.Properties) { foreach (IProperty property in typeDef.Properties) {
if (property.Name == propertyReference.Name if (property.Name == propertyReference.Name
@ -399,7 +408,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
ev = FindNonGenericEvent(eventReference); ev = FindNonGenericEvent(eventReference);
if (eventReference.DeclaringType.IsGenericInstance) { if (eventReference.DeclaringType.IsGenericInstance) {
var git = (GenericInstanceType)eventReference.DeclaringType; var git = (GenericInstanceType)eventReference.DeclaringType;
var typeArguments = git.GenericArguments.SelectArray(Resolve); var typeArguments = git.GenericArguments.SelectArray(ResolveInSignature);
ev = (IEvent)ev.Specialize(new TypeParameterSubstitution(typeArguments, null)); ev = (IEvent)ev.Specialize(new TypeParameterSubstitution(typeArguments, null));
} }
eventLookupCache.Add(eventReference, ev); eventLookupCache.Add(eventReference, ev);

2
ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs

@ -30,7 +30,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
TypeDefinition GetCecil(ITypeDefinition typeDefinition); TypeDefinition GetCecil(ITypeDefinition typeDefinition);
MemberReference GetCecil(IMember member); MemberReference GetCecil(IMember member);
IType Resolve(TypeReference typeReference); IType Resolve(TypeReference typeReference, bool isFromSignature = false);
IField Resolve(FieldReference fieldReference); IField Resolve(FieldReference fieldReference);
IMethod Resolve(MethodReference methodReference); IMethod Resolve(MethodReference methodReference);

4
ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs

@ -51,9 +51,9 @@ namespace ICSharpCode.Decompiler.TypeSystem
get { return substitution; } get { return substitution; }
} }
public IType Resolve(Mono.Cecil.TypeReference typeReference) public IType Resolve(Mono.Cecil.TypeReference typeReference, bool isFromSignature)
{ {
return context.Resolve(typeReference).AcceptVisitor(substitution); return context.Resolve(typeReference, isFromSignature).AcceptVisitor(substitution);
} }
public IField Resolve(Mono.Cecil.FieldReference fieldReference) public IField Resolve(Mono.Cecil.FieldReference fieldReference)

Loading…
Cancel
Save