Browse Source

Remove hack from ExpressionTransforms.TransformDynamicAddAssignOrRemoveAssign, implement VisitDynamicSetIndexInstruction

pull/1165/head
Siegfried Pammer 7 years ago
parent
commit
a30c628e1f
  1. 63
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs

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

@ -359,6 +359,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if (!isEvent.Argument.Match(getMember.Target).Success)
return false;
if (!SemanticHelper.IsPure(isEvent.Argument.Flags))
return false;
if (!(trueInst is DynamicInvokeMemberInstruction invokeMember))
return false;
if (!(invokeMember.BinderFlags.HasFlag(CSharpBinderFlags.InvokeSpecialName) && invokeMember.BinderFlags.HasFlag(CSharpBinderFlags.ResultDiscarded)))
@ -381,13 +383,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
context.Step("+= / -= dynamic.isevent pattern -> dynamic.compound.op", inst);
inst.ReplaceWith(dynamicCompoundAssign);
if (getMember.Target.MatchLdLoc(out var v) && v.Kind == VariableKind.Local && v.IsSingleDefinition && v.LoadCount == 1 && v.StoreInstructions[0] is StLoc initStore) {
if (ILInlining.CanInlineInto(dynamicCompoundAssign, v, initStore.Value)) {
// HACK: if inlining is possible, we can 'cheat' a bit and change the variable kind to StackSlot
// so inlining or copy propagation will take care of the extra compiler-generated local.
v.Kind = VariableKind.StackSlot;
}
}
return true;
}
@ -398,30 +393,54 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// </summary>
protected internal override void VisitDynamicSetMemberInstruction(DynamicSetMemberInstruction inst)
{
if (!inst.BinderFlags.HasFlag(CSharpBinderFlags.ValueFromCompoundAssignment)) {
base.VisitDynamicSetMemberInstruction(inst);
base.VisitDynamicSetMemberInstruction(inst);
if (!inst.BinderFlags.HasFlag(CSharpBinderFlags.ValueFromCompoundAssignment))
return;
}
if (!(inst.Value is DynamicBinaryOperatorInstruction binaryOp)) {
base.VisitDynamicSetMemberInstruction(inst);
if (!(inst.Value is DynamicBinaryOperatorInstruction binaryOp))
return;
}
if (!(binaryOp.Left is DynamicGetMemberInstruction dynamicGetMember)) {
base.VisitDynamicSetMemberInstruction(inst);
if (!(binaryOp.Left is DynamicGetMemberInstruction dynamicGetMember))
return;
}
if (!dynamicGetMember.Target.Match(inst.Target).Success) {
base.VisitDynamicSetMemberInstruction(inst);
if (!dynamicGetMember.Target.Match(inst.Target).Success)
return;
}
if (inst.Name != dynamicGetMember.Name || !DynamicCompoundAssign.IsExpressionTypeSupported(binaryOp.Operation)) {
base.VisitDynamicSetMemberInstruction(inst);
if (!SemanticHelper.IsPure(dynamicGetMember.Target.Flags))
return;
if (inst.Name != dynamicGetMember.Name || !DynamicCompoundAssign.IsExpressionTypeSupported(binaryOp.Operation))
return;
}
context.Step("dynamic.setmember.compound -> dynamic.compound.op", inst);
inst.ReplaceWith(new DynamicCompoundAssign(binaryOp.Operation, binaryOp.BinderFlags, binaryOp.Left, binaryOp.LeftArgumentInfo, binaryOp.Right, binaryOp.RightArgumentInfo));
}
/// <summary>
/// dynamic.setindex.compound(target, index, dynamic.binary.operator op(dynamic.getindex(target, index), value))
/// =>
/// dynamic.compound.op (dynamic.getindex(target, index), value)
/// </summary>
protected internal override void VisitDynamicSetIndexInstruction(DynamicSetIndexInstruction inst)
{
base.VisitDynamicSetIndexInstruction(inst);
if (!inst.BinderFlags.HasFlag(CSharpBinderFlags.ValueFromCompoundAssignment))
return;
if (!(inst.Arguments.LastOrDefault() is DynamicBinaryOperatorInstruction binaryOp))
return;
if (!(binaryOp.Left is DynamicGetIndexInstruction dynamicGetIndex))
return;
if (inst.Arguments.Count != dynamicGetIndex.Arguments.Count + 1)
return;
// Ensure that same arguments are passed to dynamicGetIndex and inst:
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)
return;
}
if (!DynamicCompoundAssign.IsExpressionTypeSupported(binaryOp.Operation))
return;
context.Step("dynamic.setindex.compound -> dynamic.compound.op", inst);
inst.ReplaceWith(new DynamicCompoundAssign(binaryOp.Operation, binaryOp.BinderFlags, binaryOp.Left, binaryOp.LeftArgumentInfo, binaryOp.Right, binaryOp.RightArgumentInfo));
}
IfInstruction HandleConditionalOperator(IfInstruction inst)
{
// if (cond) stloc (A, V1) else stloc (A, V2) --> stloc (A, if (cond) V1 else V2)

Loading…
Cancel
Save