|
|
@ -303,6 +303,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms |
|
|
|
// Get display class info
|
|
|
|
if (!IsDisplayClassLoad(target, out var displayClassLoad) || !displayClasses.TryGetValue(displayClassLoad, out var displayClass)) |
|
|
|
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 DisplayClassVariable info)) { |
|
|
|
// If the display class field was previously initialized, we use a simple assignment.
|
|
|
@ -321,7 +325,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms |
|
|
|
if (displayClass.IsMono && displayClass.CaptureScope == null && !IsOuterClosureReference(field)) { |
|
|
|
displayClass.CaptureScope = BlockContainer.FindClosestContainer(inst); |
|
|
|
} |
|
|
|
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 StLoc(v, inst.Value).WithILRange(inst)); |
|
|
@ -365,12 +369,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms |
|
|
|
// Get display class info
|
|
|
|
if (!IsDisplayClassLoad(inst.Target, out var displayClassLoad) || !displayClasses.TryGetValue(displayClassLoad, out var displayClass)) |
|
|
|
return; |
|
|
|
// Use the unspecialized member definition to make reference comparisons in dictionary possible.
|
|
|
|
var field = (IField)inst.Field.MemberDefinition; |
|
|
|
// However, we want the specialized version, so that display-class type parameters are
|
|
|
|
// substituted with the type parameters from the use-site.
|
|
|
|
var fieldType = inst.Field.Type; |
|
|
|
if (!displayClass.Variables.TryGetValue(field, out DisplayClassVariable info)) { |
|
|
|
context.Step($"Introduce captured variable for {field.FullName}", inst); |
|
|
|
// Introduce a fresh variable for the display class field.
|
|
|
|
Debug.Assert(displayClass.Definition == field.DeclaringTypeDefinition); |
|
|
|
var v = displayClass.DeclaringFunction.RegisterVariable(VariableKind.Local, GetVariableTypeFromClosureField(field), field.Name); |
|
|
|
var v = displayClass.DeclaringFunction.RegisterVariable(VariableKind.Local, fieldType, field.Name); |
|
|
|
v.HasInitialValue = true; |
|
|
|
v.CaptureScope = displayClass.CaptureScope; |
|
|
|
inst.ReplaceWith(new LdLoca(v).WithILRange(inst)); |
|
|
@ -381,20 +389,5 @@ namespace ICSharpCode.Decompiler.IL.Transforms |
|
|
|
Debug.Fail("LdFlda pattern not supported!"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
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]; |
|
|
|
} |
|
|
|
} |
|
|
|
} |