Browse Source

Merge branch '5.0.x' of https://github.com/icsharpcode/ILSpy

pull/1790/head
Siegfried Pammer 6 years ago
parent
commit
8470d87cb5
  1. 9
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs
  2. 30
      ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs

9
ICSharpCode.Decompiler.Tests/TestCases/Pretty/DelegateConstruction.cs

@ -376,5 +376,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -376,5 +376,14 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
return captured;
};
}
public static Func<TCaptured> CapturedTypeParameter2<TNonCaptured, TCaptured>(TNonCaptured a, Func<TNonCaptured, List<TCaptured>> f)
{
List<TCaptured> captured = f(a);
return delegate {
Console.WriteLine(captured.GetType().FullName);
return captured.FirstOrDefault();
};
}
}
}

30
ICSharpCode.Decompiler/IL/Transforms/TransformDisplayClassUsage.cs

@ -278,11 +278,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -278,11 +278,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
inst.Value.AcceptVisitor(this);
if (IsParameterAssignment(inst, out var displayClass, out var field, out var parameter)) {
context.Step($"Detected parameter assignment {parameter.Name}", inst);
displayClass.Variables.Add(field, parameter);
displayClass.Variables.Add((IField)field.MemberDefinition, parameter);
instructionsToRemove.Add(inst);
} else if (IsDisplayClassAssignment(inst, out displayClass, out field, out var variable)) {
context.Step($"Detected display-class assignment {variable.Name}", inst);
displayClass.Variables.Add(field, variable);
displayClass.Variables.Add((IField)field.MemberDefinition, variable);
instructionsToRemove.Add(inst);
} else {
inst.Target.AcceptVisitor(this);
@ -324,7 +324,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -324,7 +324,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if (!(inst.Value.MatchLdLoc(out var v) && v.Kind == VariableKind.Parameter && v.Function == currentFunction))
return false;
if (displayClass.Variables.ContainsKey(field))
if (displayClass.Variables.ContainsKey((IField)field.MemberDefinition))
return false;
if (displayClassVar.Function != currentFunction)
return false;
@ -339,7 +339,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -339,7 +339,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
field = null;
if (!(inst is LdFlda ldflda))
return false;
field = (IField)ldflda.Field.MemberDefinition;
field = ldflda.Field;
return IsDisplayClassLoad(ldflda.Target, out displayClassVar)
&& displayClasses.TryGetValue(displayClassVar, out displayClass);
}
@ -350,11 +350,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -350,11 +350,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms
// Get display class info
if (!IsDisplayClassFieldAccess(inst, out _, out DisplayClass displayClass, out IField field))
return;
// We want the specialized version, so that display-class type parameters are
// substituted with the type parameters from the use-site.
var fieldType = field.Type;
// However, use the unspecialized member definition to make reference comparisons in dictionary possible.
field = (IField)field.MemberDefinition;
if (!displayClass.Variables.TryGetValue(field, out var v)) {
context.Step($"Introduce captured variable for {field.FullName}", inst);
// Introduce a fresh variable for the display class field.
Debug.Assert(displayClass.Definition == field.DeclaringTypeDefinition);
v = displayClass.DeclaringFunction.RegisterVariable(VariableKind.Local, GetVariableTypeFromClosureField(field), field.Name);
v = displayClass.DeclaringFunction.RegisterVariable(VariableKind.Local, fieldType, field.Name);
v.HasInitialValue = true;
v.CaptureScope = displayClass.CaptureScope;
inst.ReplaceWith(new LdLoca(v).WithILRange(inst));
@ -364,20 +369,5 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -364,20 +369,5 @@ namespace ICSharpCode.Decompiler.IL.Transforms
inst.ReplaceWith(new LdLoca(v).WithILRange(inst));
}
}
private IType GetVariableTypeFromClosureField(IField field)
{
if (!(field.Type is ITypeParameter typeParameter))
return field.Type;
var rootMethod = context.Function.Method;
if (typeParameter.Owner != field.DeclaringTypeDefinition)
return field.Type;
if (typeParameter.Index >= rootMethod.TypeParameters.Count) {
Debug.Assert(false, "Cannot map display-class type parameter to method type parameter");
return field.Type;
}
return rootMethod.TypeParameters[typeParameter.Index];
}
}
}

Loading…
Cancel
Save