diff --git a/ICSharpCode.Decompiler/IL/Transforms/CachedDelegateInitialization.cs b/ICSharpCode.Decompiler/IL/Transforms/CachedDelegateInitialization.cs index b16254a91..269198dd7 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/CachedDelegateInitialization.cs +++ b/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; } + + /// + /// 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) + /// + 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; + } } }