Browse Source

Add support for rare VB cached delegate construction pattern with return

pull/2844/head
ElektroKill 3 years ago
parent
commit
b193c2a6a2
No known key found for this signature in database
GPG Key ID: 7E3C5C084E40E3EC
  1. 33
      ICSharpCode.Decompiler/IL/Transforms/CachedDelegateInitialization.cs

33
ICSharpCode.Decompiler/IL/Transforms/CachedDelegateInitialization.cs

@ -55,6 +55,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -55,6 +55,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
continue;
}
if (CachedDelegateInitializationVBWithReturn(inst))
{
block.Instructions.RemoveAt(i);
continue;
}
if (CachedDelegateInitializationVBWithClosure(inst))
{
continue;
@ -241,6 +246,34 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -241,6 +246,34 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
/// <summary>
/// if (comp.o(ldsfld CachedAnonMethodDelegate != ldnull)) {
/// leave IL_0005 (ldsfld CachedAnonMethodDelegate)
/// }
/// leave IL_0005 (stsfld CachedAnonMethodDelegate(DelegateConstruction))
/// =>
/// leave IL_0005 (DelegateConstruction)
/// </summary>
bool CachedDelegateInitializationVBWithReturn(IfInstruction inst)
{
if (!inst.Condition.MatchCompNotEqualsNull(out var arg) || !arg.MatchLdsFld(out var field))
return false;
if (!inst.FalseInst.MatchNop())
return false;
if (!inst.TrueInst.MatchReturn(out arg) || !arg.MatchLdsFld(field))
return false;
var leaveAfterIf = inst.Parent.Children.ElementAtOrDefault(inst.ChildIndex + 1) as Leave;
if (leaveAfterIf is null || !leaveAfterIf.IsLeavingFunction)
return false;
if (!leaveAfterIf.Value.MatchStsFld(out var field2, out var delegateConstruction) || !field.Equals(field2))
return false;
if (!DelegateConstruction.MatchDelegateConstruction(delegateConstruction, out _, out _, out _, true))
return false;
context.Step("CachedDelegateInitializationVBWithReturn", inst);
leaveAfterIf.Value = delegateConstruction;
return true;
}
/// <summary>
/// if (comp.o(ldobj delegateType(ldflda CachedAnonMethodDelegate(ldloc closure)) != ldnull)) Block {
/// stloc s(ldobj delegateType(ldflda CachedAnonMethodDelegate(ldloc closure)))

Loading…
Cancel
Save