Browse Source

Add support for VB.NET cached delegate initialization with closures

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

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

@ -1,4 +1,4 @@
// Copyright (c) 2011-2016 Siegfried Pammer
// Copyright (c) 2011-2016 Siegfried Pammer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
@ -55,6 +55,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
continue;
}
if (CachedDelegateInitializationVBWithClosure(inst))
{
continue;
}
}
}
}
@ -236,5 +240,48 @@ namespace ICSharpCode.Decompiler.IL.Transforms
inst.ReplaceWith(new StLoc(s, delegateConstruction));
return true;
}
/// <summary>
/// if (comp.o(ldobj delegateType(ldflda CachedAnonMethodDelegate(ldloc closure)) != ldnull)) Block {
/// stloc s(ldobj delegateType(ldflda CachedAnonMethodDelegate(ldloc closure)))
/// } else Block {
/// stloc s(stobj delegateType(ldflda CachedAnonMethodDelegate(ldloc closure), DelegateConstruction))
/// }
/// =>
/// stloc s(DelegateConstruction)
/// </summary>
bool CachedDelegateInitializationVBWithClosure(IfInstruction inst)
{
if (!(inst.TrueInst is Block trueInst && inst.FalseInst is Block falseInst))
return false;
if (trueInst.Instructions.Count != 1 || falseInst.Instructions.Count != 1)
return false;
if (!(trueInst.Instructions[0].MatchStLoc(out var s, out var trueInitValue)
&& falseInst.Instructions[0].MatchStLoc(s, out var falseInitValue)))
{
return false;
}
if (s.Kind != VariableKind.StackSlot || s.StoreCount != 2 || s.LoadCount != 1)
return false;
if (!(falseInitValue is StObj stobj) || !(trueInitValue is LdObj ldobj))
return false;
if (!(stobj.Value is NewObj delegateConstruction))
return false;
if (!stobj.Target.MatchLdFlda(out var target1, out var field1)
|| !ldobj.Target.MatchLdFlda(out var target2, out var field2)
|| !field1.Equals(field2) || !target1.Match(target2).Success)
{
return false;
}
if (!inst.Condition.MatchCompNotEqualsNull(out ILInstruction left))
return false;
if (!ldobj.Match(left).Success)
return false;
if (!DelegateConstruction.MatchDelegateConstruction(delegateConstruction, out _, out _, out _, true))
return false;
context.Step("CachedDelegateInitializationVBWithClosure", inst);
inst.ReplaceWith(new StLoc(s, delegateConstruction));
return true;
}
}
}
Loading…
Cancel
Save