|
|
@ -31,32 +31,42 @@ namespace ICSharpCode.Decompiler.IL.Transforms |
|
|
|
{ |
|
|
|
{ |
|
|
|
ILTransformContext context; |
|
|
|
ILTransformContext context; |
|
|
|
ITypeResolveContext decompilationContext; |
|
|
|
ITypeResolveContext decompilationContext; |
|
|
|
|
|
|
|
readonly Stack<MethodDefinitionHandle> activeMethods = new Stack<MethodDefinitionHandle>(); |
|
|
|
|
|
|
|
|
|
|
|
void IILTransform.Run(ILFunction function, ILTransformContext context) |
|
|
|
void IILTransform.Run(ILFunction function, ILTransformContext context) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (!context.Settings.AnonymousMethods) |
|
|
|
if (!context.Settings.AnonymousMethods) |
|
|
|
return; |
|
|
|
return; |
|
|
|
this.context = context; |
|
|
|
var prevContext = this.context; |
|
|
|
this.decompilationContext = new SimpleTypeResolveContext(function.Method); |
|
|
|
var prevDecompilationContext = this.decompilationContext; |
|
|
|
var cancellationToken = context.CancellationToken; |
|
|
|
try { |
|
|
|
foreach (var inst in function.Descendants) { |
|
|
|
activeMethods.Push((MethodDefinitionHandle)function.Method.MetadataToken); |
|
|
|
cancellationToken.ThrowIfCancellationRequested(); |
|
|
|
this.context = context; |
|
|
|
if (inst is NewObj call) { |
|
|
|
this.decompilationContext = new SimpleTypeResolveContext(function.Method); |
|
|
|
context.StepStartGroup($"TransformDelegateConstruction {call.StartILOffset}", call); |
|
|
|
var cancellationToken = context.CancellationToken; |
|
|
|
ILFunction f = TransformDelegateConstruction(call, out ILInstruction target); |
|
|
|
foreach (var inst in function.Descendants) { |
|
|
|
if (f != null && target is IInstructionWithVariableOperand instWithVar) { |
|
|
|
cancellationToken.ThrowIfCancellationRequested(); |
|
|
|
if (instWithVar.Variable.Kind == VariableKind.Local) { |
|
|
|
if (inst is NewObj call) { |
|
|
|
instWithVar.Variable.Kind = VariableKind.DisplayClassLocal; |
|
|
|
context.StepStartGroup($"TransformDelegateConstruction {call.StartILOffset}", call); |
|
|
|
} |
|
|
|
ILFunction f = TransformDelegateConstruction(call, out ILInstruction target); |
|
|
|
var displayClassTypeDef = instWithVar.Variable.Type.GetDefinition(); |
|
|
|
if (f != null && target is IInstructionWithVariableOperand instWithVar) { |
|
|
|
if (instWithVar.Variable.IsSingleDefinition && instWithVar.Variable.StoreInstructions.SingleOrDefault() is StLoc store) { |
|
|
|
if (instWithVar.Variable.Kind == VariableKind.Local) { |
|
|
|
if (store.Value is NewObj newObj) { |
|
|
|
instWithVar.Variable.Kind = VariableKind.DisplayClassLocal; |
|
|
|
instWithVar.Variable.CaptureScope = BlockContainer.FindClosestContainer(store); |
|
|
|
} |
|
|
|
|
|
|
|
var displayClassTypeDef = instWithVar.Variable.Type.GetDefinition(); |
|
|
|
|
|
|
|
if (instWithVar.Variable.IsSingleDefinition && instWithVar.Variable.StoreInstructions.SingleOrDefault() is StLoc store) { |
|
|
|
|
|
|
|
if (store.Value is NewObj newObj) { |
|
|
|
|
|
|
|
instWithVar.Variable.CaptureScope = BlockContainer.FindClosestContainer(store); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
context.StepEndGroup(); |
|
|
|
} |
|
|
|
} |
|
|
|
context.StepEndGroup(); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} finally { |
|
|
|
|
|
|
|
this.context = prevContext; |
|
|
|
|
|
|
|
this.decompilationContext = prevDecompilationContext; |
|
|
|
|
|
|
|
activeMethods.Pop(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -131,6 +141,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms |
|
|
|
if (LocalFunctionDecompiler.IsLocalFunctionMethod(targetMethod, context)) |
|
|
|
if (LocalFunctionDecompiler.IsLocalFunctionMethod(targetMethod, context)) |
|
|
|
return null; |
|
|
|
return null; |
|
|
|
target = value.Arguments[0]; |
|
|
|
target = value.Arguments[0]; |
|
|
|
|
|
|
|
var handle = (MethodDefinitionHandle)targetMethod.MetadataToken; |
|
|
|
|
|
|
|
if (activeMethods.Contains(handle)) { |
|
|
|
|
|
|
|
this.context.Function.Warnings.Add(" Found self-referencing delegate construction. Abort transformation to avoid stack overflow."); |
|
|
|
|
|
|
|
return null; |
|
|
|
|
|
|
|
} |
|
|
|
var methodDefinition = context.PEFile.Metadata.GetMethodDefinition((MethodDefinitionHandle)targetMethod.MetadataToken); |
|
|
|
var methodDefinition = context.PEFile.Metadata.GetMethodDefinition((MethodDefinitionHandle)targetMethod.MetadataToken); |
|
|
|
if (!methodDefinition.HasBody()) |
|
|
|
if (!methodDefinition.HasBody()) |
|
|
|
return null; |
|
|
|
return null; |
|
|
@ -157,7 +172,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms |
|
|
|
function.AcceptVisitor(new ReplaceDelegateTargetVisitor(target, function.Variables.SingleOrDefault(v => v.Index == -1 && v.Kind == VariableKind.Parameter))); |
|
|
|
function.AcceptVisitor(new ReplaceDelegateTargetVisitor(target, function.Variables.SingleOrDefault(v => v.Index == -1 && v.Kind == VariableKind.Parameter))); |
|
|
|
// handle nested lambdas
|
|
|
|
// handle nested lambdas
|
|
|
|
nestedContext.StepStartGroup("DelegateConstruction (nested lambdas)", function); |
|
|
|
nestedContext.StepStartGroup("DelegateConstruction (nested lambdas)", function); |
|
|
|
((IILTransform)new DelegateConstruction()).Run(function, nestedContext); |
|
|
|
((IILTransform)this).Run(function, nestedContext); |
|
|
|
nestedContext.StepEndGroup(); |
|
|
|
nestedContext.StepEndGroup(); |
|
|
|
function.AddILRange(target); |
|
|
|
function.AddILRange(target); |
|
|
|
function.AddILRange(value); |
|
|
|
function.AddILRange(value); |
|
|
|