Browse Source

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

pull/734/head
Siegfried Pammer 9 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 @@ -783,15 +783,15 @@ namespace ICSharpCode.Decompiler.CSharp
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);
// Create AnonymousMethodExpression and prepare parameters
AnonymousMethodExpression ame = new AnonymousMethodExpression();
ame.Parameters.AddRange(MakeParameters(method, function));
ame.HasParameterList = true;
StatementBuilder builder = new StatementBuilder(typeSystem, decompilationContext, method);
var context = new SimpleTypeResolveContext(method);
StatementBuilder builder = new StatementBuilder(typeSystem.GetSpecializingTypeSystem(context), context, method);
var body = builder.ConvertAsBlock(function.Body);
bool isLambda = false;
@ -1274,12 +1274,17 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1274,12 +1274,17 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitIfInstruction(IfInstruction inst)
{
var condition = TranslateCondition(inst.Condition);
var targetType = compilation.FindType(inst.ResultType.ToKnownTypeCode());
var trueBranch = Translate(inst.TrueInst).ConvertTo(targetType, this);
var falseBranch = Translate(inst.FalseInst).ConvertTo(targetType, this);
return new ConditionalExpression(condition.Expression, trueBranch.Expression, falseBranch.Expression)
var trueBranch = Translate(inst.TrueInst);
var falseBranch = Translate(inst.FalseInst);
IType targetType;
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)
.WithRR(new ResolveResult(trueBranch.Type));
.WithRR(new ResolveResult(targetType));
}
protected internal override TranslatedExpression VisitAddressOf(AddressOf inst)

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

@ -49,8 +49,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -49,8 +49,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
block.Instructions.RemoveAt(i);
continue;
}
if (CachedDelegateInitializationWithLocal(inst)) {
bool hasFieldStore;
if (CachedDelegateInitializationWithLocal(inst, out hasFieldStore)) {
block.Instructions.RemoveAt(i);
if (hasFieldStore) {
block.Instructions.RemoveAt(i - 1);
}
continue;
}
}
@ -96,7 +100,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -96,7 +100,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var targetMethod = ((IInstructionWithMethodOperand)value.Arguments[1]).Method;
if (IsAnonymousMethod(decompilationContext.CurrentTypeDefinition, targetMethod)) {
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 contextPrefix = targetMethod.Name;
@ -173,9 +177,48 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -173,9 +177,48 @@ namespace ICSharpCode.Decompiler.IL.Transforms
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 @@ -33,7 +33,8 @@ namespace ICSharpCode.Decompiler
IMethod method = decompilationContext.CurrentMember as IMethod;
if (method != null)
methodTypeParameters = method.TypeArguments;
if (typeSystem is SpecializingDecompilerTypeSystem)
typeSystem = ((SpecializingDecompilerTypeSystem)typeSystem).Context;
if ((classTypeParameters != null && classTypeParameters.Count > 0) || (methodTypeParameters != null && methodTypeParameters.Count > 0))
return new SpecializingDecompilerTypeSystem(typeSystem, new TypeParameterSubstitution(classTypeParameters, methodTypeParameters));
else

4
ICSharpCode.Decompiler/TypeSystem/SpecializingDecompilerTypeSystem.cs

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

Loading…
Cancel
Save