Browse Source

Fix dynamic compound assignments

pull/1612/head
Siegfried Pammer 6 years ago
parent
commit
adc443e4e2
  1. 37
      ICSharpCode.Decompiler/IL/Transforms/DynamicIsEventAssignmentTransform.cs
  2. 6
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs

37
ICSharpCode.Decompiler/IL/Transforms/DynamicIsEventAssignmentTransform.cs

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Linq;
namespace ICSharpCode.Decompiler.IL.Transforms
{
public class DynamicIsEventAssignmentTransform : IStatementTransform
@ -24,6 +26,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -24,6 +26,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// if (logic.not(ldloc V_1)) Block IL_004a {
/// stloc V_2(dynamic.getmember B(target))
/// }
/// [stloc copyOfValue(value)]
/// if (logic.not(ldloc V_1)) Block IL_0149 {
/// dynamic.setmember.compound B(target, dynamic.binary.operator AddAssign(ldloc V_2, value))
/// } else Block IL_0151 {
@ -41,11 +44,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -41,11 +44,17 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return;
if (!(flagVar.IsSingleDefinition && flagVar.LoadCount == 2))
return;
if (!(MatchLhsCacheIfInstruction(block.Instructions[pos + 1], flagVar, out var dynamicGetMemberStore)))
if (!MatchLhsCacheIfInstruction(block.Instructions[pos + 1], flagVar, out var dynamicGetMemberStore))
return;
if (!(dynamicGetMemberStore.MatchStLoc(out var getMemberVar, out inst) && inst is DynamicGetMemberInstruction getMemberInst))
return;
foreach (var descendant in block.Instructions[pos + 2].Descendants) {
int offset = 2;
if (block.Instructions[pos + offset].MatchStLoc(out var valueVariable)
&& pos + 4 < block.Instructions.Count && valueVariable.IsSingleDefinition && valueVariable.LoadCount == 2
&& valueVariable.LoadInstructions.All(ld => ld.Parent is DynamicInstruction)) {
offset++;
}
foreach (var descendant in block.Instructions[pos + offset].Descendants) {
if (!MatchIsEventAssignmentIfInstruction(descendant, isEvent, flagVar, getMemberVar, out var setMemberInst, out var getMemberVarUse, out var isEventConditionUse))
continue;
context.Step("DynamicIsEventAssignmentTransform", block.Instructions[pos]);
@ -86,12 +95,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -86,12 +95,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
isEventConditionUse = condition;
} else
return false;
setMemberInst = Block.Unwrap(trueInst) as DynamicSetMemberInstruction;
if (!(setMemberInst != null))
setMemberInst = UnwrapBlockAndUnusedStore(trueInst) as DynamicSetMemberInstruction;
if (setMemberInst == null)
return false;
if (!isEvent.Argument.Match(setMemberInst.Target).Success)
return false;
if (!(Block.Unwrap(falseInst) is DynamicInvokeMemberInstruction invokeMemberInst && invokeMemberInst.Arguments.Count == 2))
if (!(UnwrapBlockAndUnusedStore(falseInst) is DynamicInvokeMemberInstruction invokeMemberInst && invokeMemberInst.Arguments.Count == 2))
return false;
if (!isEvent.Argument.Match(invokeMemberInst.Arguments[0]).Success)
return false;
@ -101,6 +110,24 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -101,6 +110,24 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return true;
}
/// <summary>
/// If <paramref name="inst"/> is a Block unwraps the block, otherwise returns inst,
/// if the block contains a stloc to a stack slot that is unused, returns the value,
/// otherwise returns inst
/// </summary>
internal static ILInstruction UnwrapBlockAndUnusedStore(ILInstruction inst)
{
var unwrapped = Block.Unwrap(inst);
if (unwrapped is StLoc stloc
&& stloc.Variable.IsSingleDefinition
&& stloc.Variable.LoadCount == 0)
{
return stloc.Value;
}
return unwrapped;
}
/// <summary>
/// if (logic.not(ldloc V_1)) Block IL_004a {
/// stloc V_2(dynamic.getmember B(target))

6
ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs

@ -497,8 +497,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -497,8 +497,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if (!(condition is DynamicIsEventInstruction isEvent))
return false;
trueInst = Block.Unwrap(trueInst);
falseInst = Block.Unwrap(falseInst);
trueInst = DynamicIsEventAssignmentTransform.UnwrapBlockAndUnusedStore(trueInst);
falseInst = DynamicIsEventAssignmentTransform.UnwrapBlockAndUnusedStore(falseInst);
if (!(falseInst is DynamicCompoundAssign dynamicCompoundAssign))
return false;
if (!(dynamicCompoundAssign.Target is DynamicGetMemberInstruction getMember))
@ -582,7 +582,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -582,7 +582,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
for (int j = 0; j < dynamicGetIndex.Arguments.Count; j++) {
if (!SemanticHelper.IsPure(dynamicGetIndex.Arguments[j].Flags))
return;
if (!dynamicGetIndex.Arguments[j].Match(dynamicGetIndex.Arguments[j]).Success)
if (!dynamicGetIndex.Arguments[j].Match(inst.Arguments[j]).Success)
return;
}
if (!DynamicCompoundAssign.IsExpressionTypeSupported(binaryOp.Operation))

Loading…
Cancel
Save