Browse Source

Fixed some bugs in DelegateConstruction (closure display-class reversal is still missing)

pull/734/head
Siegfried Pammer 10 years ago
parent
commit
ffda608f47
  1. 23
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  2. 51
      ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs
  3. 3
      ICSharpCode.Decompiler/NRExtensions.cs
  4. 4
      ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs

23
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -783,15 +783,15 @@ namespace ICSharpCode.Decompiler.CSharp
TranslatedExpression TranslateFunction(TranslatedExpression objectCreateExpression, TranslatedExpression target, ILFunction function) TranslatedExpression TranslateFunction(TranslatedExpression objectCreateExpression, TranslatedExpression target, ILFunction function)
{ {
var method = typeSystem.Resolve(function.Method) as IMethod; var method = typeSystem.Resolve(function.Method)?.MemberDefinition as IMethod;
Debug.Assert(method != null); Debug.Assert(method != null);
// Create AnonymousMethodExpression and prepare parameters // Create AnonymousMethodExpression and prepare parameters
AnonymousMethodExpression ame = new AnonymousMethodExpression(); AnonymousMethodExpression ame = new AnonymousMethodExpression();
ame.Parameters.AddRange(MakeParameters(method, function)); ame.Parameters.AddRange(MakeParameters(method, function));
ame.HasParameterList = true; ame.HasParameterList = true;
var context = new SimpleTypeResolveContext(method);
StatementBuilder builder = new StatementBuilder(typeSystem, decompilationContext, method); StatementBuilder builder = new StatementBuilder(typeSystem.GetSpecializingTypeSystem(context), context, method);
var body = builder.ConvertAsBlock(function.Body); var body = builder.ConvertAsBlock(function.Body);
bool isLambda = false; bool isLambda = false;
@ -1274,12 +1274,17 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitIfInstruction(IfInstruction inst) protected internal override TranslatedExpression VisitIfInstruction(IfInstruction inst)
{ {
var condition = TranslateCondition(inst.Condition); var condition = TranslateCondition(inst.Condition);
var targetType = compilation.FindType(inst.ResultType.ToKnownTypeCode()); var trueBranch = Translate(inst.TrueInst);
var trueBranch = Translate(inst.TrueInst).ConvertTo(targetType, this); var falseBranch = Translate(inst.FalseInst);
var falseBranch = Translate(inst.FalseInst).ConvertTo(targetType, this); IType targetType;
return new ConditionalExpression(condition.Expression, trueBranch.Expression, falseBranch.Expression) if (!trueBranch.Type.Equals(SpecialType.NullType) && !falseBranch.Type.Equals(SpecialType.NullType)) {
targetType = compilation.FindType(inst.ResultType.ToKnownTypeCode());
} else {
targetType = trueBranch.Type.Equals(SpecialType.NullType) ? falseBranch.Type : trueBranch.Type;
}
return new ConditionalExpression(condition.Expression, trueBranch.ConvertTo(targetType, this).Expression, falseBranch.ConvertTo(targetType, this).Expression)
.WithILInstruction(inst) .WithILInstruction(inst)
.WithRR(new ResolveResult(trueBranch.Type)); .WithRR(new ResolveResult(targetType));
} }
protected internal override TranslatedExpression VisitAddressOf(AddressOf inst) protected internal override TranslatedExpression VisitAddressOf(AddressOf inst)

51
ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs

@ -49,8 +49,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
block.Instructions.RemoveAt(i); block.Instructions.RemoveAt(i);
continue; continue;
} }
if (CachedDelegateInitializationWithLocal(inst)) { bool hasFieldStore;
if (CachedDelegateInitializationWithLocal(inst, out hasFieldStore)) {
block.Instructions.RemoveAt(i); block.Instructions.RemoveAt(i);
if (hasFieldStore) {
block.Instructions.RemoveAt(i - 1);
}
continue; continue;
} }
} }
@ -96,7 +100,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var targetMethod = ((IInstructionWithMethodOperand)value.Arguments[1]).Method; var targetMethod = ((IInstructionWithMethodOperand)value.Arguments[1]).Method;
if (IsAnonymousMethod(decompilationContext.CurrentTypeDefinition, targetMethod)) { if (IsAnonymousMethod(decompilationContext.CurrentTypeDefinition, targetMethod)) {
var target = value.Arguments[0]; var target = value.Arguments[0];
var localTypeSystem = context.TypeSystem.GetSpecializingTypeSystem(decompilationContext); var localTypeSystem = context.TypeSystem.GetSpecializingTypeSystem(new SimpleTypeResolveContext(targetMethod));
var function = ILFunction.Read(localTypeSystem, targetMethod, context.CancellationToken); var function = ILFunction.Read(localTypeSystem, targetMethod, context.CancellationToken);
var contextPrefix = targetMethod.Name; var contextPrefix = targetMethod.Name;
@ -173,9 +177,48 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true; return true;
} }
bool CachedDelegateInitializationWithLocal(IfInstruction inst) bool CachedDelegateInitializationWithLocal(IfInstruction inst, out bool hasFieldStore)
{ {
return false; // [stloc v(ldsfld CachedAnonMethodDelegate)]
// if (comp(ldloc v == ldnull) {
// stloc v(DelegateConstruction)
// [stsfld CachedAnonMethodDelegate(v)]
// }
// ... one usage of v ...
// =>
// ... one usage of DelegateConstruction ...
Block trueInst = inst.TrueInst as Block;
var condition = inst.Condition as Comp;
hasFieldStore = false;
if (condition == null || trueInst == null || (trueInst.Instructions.Count != 1 && trueInst.Instructions.Count != 2) || !inst.FalseInst.MatchNop())
return false;
ILVariable v;
ILInstruction value, value2;
var storeInst = trueInst.Instructions[0];
var optionalFieldStore = trueInst.Instructions.ElementAtOrDefault(1);
if (!condition.Left.MatchLdLoc(out v) || !condition.Right.MatchLdNull())
return false;
if (!storeInst.MatchStLoc(v, out value))
return false;
if (optionalFieldStore != null) {
IField field, field2;
if (!optionalFieldStore.MatchStsFld(out value2, out field) || !value2.MatchLdLoc(v) || !field.IsCompilerGeneratedOrIsInCompilerGeneratedClass())
return false;
var storeBeforeIf = inst.Parent.Children.ElementAtOrDefault(inst.ChildIndex - 1) as StLoc;
if (storeBeforeIf == null || storeBeforeIf.Variable != v || !storeBeforeIf.Value.MatchLdsFld(out field2) || !field.Equals(field2))
return false;
hasFieldStore = true;
}
if (!IsDelegateConstruction(value as NewObj, true))
return false;
var nextInstruction = inst.Parent.Children.ElementAtOrDefault(inst.ChildIndex + 1);
if (nextInstruction == null)
return false;
var usages = nextInstruction.Descendants.OfType<LdLoc>().Where(i => i.Variable == v).ToArray();
if (usages.Length != 1)
return false;
usages[0].ReplaceWith(value);
return true;
} }
} }
} }

3
ICSharpCode.Decompiler/NRExtensions.cs

@ -33,7 +33,8 @@ namespace ICSharpCode.Decompiler
IMethod method = decompilationContext.CurrentMember as IMethod; IMethod method = decompilationContext.CurrentMember as IMethod;
if (method != null) if (method != null)
methodTypeParameters = method.TypeArguments; methodTypeParameters = method.TypeArguments;
if (typeSystem is SpecializingDecompilerTypeSystem)
typeSystem = ((SpecializingDecompilerTypeSystem)typeSystem).Context;
if ((classTypeParameters != null && classTypeParameters.Count > 0) || (methodTypeParameters != null && methodTypeParameters.Count > 0)) if ((classTypeParameters != null && classTypeParameters.Count > 0) || (methodTypeParameters != null && methodTypeParameters.Count > 0))
return new SpecializingDecompilerTypeSystem(typeSystem, new TypeParameterSubstitution(classTypeParameters, methodTypeParameters)); return new SpecializingDecompilerTypeSystem(typeSystem, new TypeParameterSubstitution(classTypeParameters, methodTypeParameters));
else else

4
ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs

@ -38,6 +38,10 @@ namespace ICSharpCode.Decompiler
this.context = context; this.context = context;
this.substitution = substitution; this.substitution = substitution;
} }
internal IDecompilerTypeSystem Context {
get { return context; }
}
public ICompilation Compilation { public ICompilation Compilation {
get { return context.Compilation; } get { return context.Compilation; }

Loading…
Cancel
Save