Browse Source

Implement UserDefinedCompoundAssign

rename CompoundAssignmentInstruction -> NumericCompoundAssign
pull/1129/head
Siegfried Pammer 7 years ago
parent
commit
845c620a9f
  1. 69
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  2. 219
      ICSharpCode.Decompiler/IL/Instructions.cs
  3. 21
      ICSharpCode.Decompiler/IL/Instructions.tt
  4. 91
      ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs
  5. 4
      ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs
  6. 19
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTransforms.cs
  7. 3
      ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs
  8. 3
      ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs

69
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -1102,8 +1102,69 @@ namespace ICSharpCode.Decompiler.CSharp
.WithILInstruction(inst)
.WithRR(resolver.ResolveBinaryOperator(op, left.ResolveResult, right.ResolveResult));
}
protected internal override TranslatedExpression VisitCompoundAssignmentInstruction(CompoundAssignmentInstruction inst, TranslationContext context)
protected internal override TranslatedExpression VisitUserDefinedCompoundAssign(UserDefinedCompoundAssign inst, TranslationContext context)
{
var target = Translate(inst.Target);
if (inst.Method.Parameters.Count == 2) {
var value = Translate(inst.Value).ConvertTo(inst.Method.Parameters[1].Type, this);
AssignmentOperatorType? op = GetAssignmentOperatorTypeFromMetadataName(inst.Method.Name);
Debug.Assert(op != null);
return new AssignmentExpression(target, op.Value, value)
.WithILInstruction(inst)
.WithRR(new OperatorResolveResult(inst.Method.ReturnType, AssignmentExpression.GetLinqNodeType(op.Value, false), inst.Method, inst.IsLifted, new[] { target.ResolveResult, value.ResolveResult }));
} else {
UnaryOperatorType? op = GetUnaryOperatorTypeFromMetadataName(inst.Method.Name, inst.CompoundAssignmentType == CompoundAssignmentType.EvaluatesToOldValue);
Debug.Assert(op != null);
return new UnaryOperatorExpression(op.Value, target)
.WithILInstruction(inst)
.WithRR(new OperatorResolveResult(inst.Method.ReturnType, UnaryOperatorExpression.GetLinqNodeType(op.Value, false), inst.Method, inst.IsLifted, new[] { target.ResolveResult }));
}
}
internal static AssignmentOperatorType? GetAssignmentOperatorTypeFromMetadataName(string name)
{
switch (name) {
case "op_Addition":
return AssignmentOperatorType.Add;
case "op_Subtraction":
return AssignmentOperatorType.Subtract;
case "op_Multiply":
return AssignmentOperatorType.Multiply;
case "op_Division":
return AssignmentOperatorType.Divide;
case "op_Modulus":
return AssignmentOperatorType.Modulus;
case "op_BitwiseAnd":
return AssignmentOperatorType.BitwiseAnd;
case "op_BitwiseOr":
return AssignmentOperatorType.BitwiseOr;
case "op_ExclusiveOr":
return AssignmentOperatorType.ExclusiveOr;
case "op_LeftShift":
return AssignmentOperatorType.ShiftLeft;
case "op_RightShift":
return AssignmentOperatorType.ShiftRight;
default:
return null;
}
}
internal static UnaryOperatorType? GetUnaryOperatorTypeFromMetadataName(string name, bool isPostfix)
{
switch (name) {
case "op_Increment":
return isPostfix ? UnaryOperatorType.PostIncrement : UnaryOperatorType.Increment;
case "op_Decrement":
return isPostfix ? UnaryOperatorType.PostDecrement : UnaryOperatorType.Decrement;
default:
return null;
}
}
protected internal override TranslatedExpression VisitNumericCompoundAssign(NumericCompoundAssign inst, TranslationContext context)
{
switch (inst.Operator) {
case BinaryNumericOperator.Add:
@ -1131,7 +1192,7 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
TranslatedExpression HandleCompoundAssignment(CompoundAssignmentInstruction inst, AssignmentOperatorType op)
TranslatedExpression HandleCompoundAssignment(NumericCompoundAssign inst, AssignmentOperatorType op)
{
var target = Translate(inst.Target);
var value = Translate(inst.Value);
@ -1196,7 +1257,7 @@ namespace ICSharpCode.Decompiler.CSharp
return resultExpr;
}
TranslatedExpression HandleCompoundShift(CompoundAssignmentInstruction inst, AssignmentOperatorType op)
TranslatedExpression HandleCompoundShift(NumericCompoundAssign inst, AssignmentOperatorType op)
{
Debug.Assert(inst.CompoundAssignmentType == CompoundAssignmentType.EvaluatesToNewValue);
var target = Translate(inst.Target);

219
ICSharpCode.Decompiler/IL/Instructions.cs

@ -45,8 +45,10 @@ namespace ICSharpCode.Decompiler.IL
PinnedRegion,
/// <summary>Common instruction for add, sub, mul, div, rem, bit.and, bit.or, bit.xor, shl and shr.</summary>
BinaryNumericInstruction,
/// <summary>Common instruction for compound assignments.</summary>
CompoundAssignmentInstruction,
/// <summary>Common instruction for numeric compound assignments.</summary>
NumericCompoundAssign,
/// <summary>Common instruction for user-defined compound assignments.</summary>
UserDefinedCompoundAssign,
/// <summary>Bitwise NOT</summary>
BitNot,
/// <summary>Retrieves the RuntimeArgumentHandle.</summary>
@ -485,6 +487,96 @@ namespace ICSharpCode.Decompiler.IL.Patterns
}
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Common instruction for compound assignments.</summary>
public abstract partial class CompoundAssignmentInstruction : ILInstruction
{
public static readonly SlotInfo TargetSlot = new SlotInfo("Target", canInlineInto: true);
ILInstruction target;
public ILInstruction Target {
get { return this.target; }
set {
ValidateChild(value);
SetChildInstruction(ref this.target, value, 0);
}
}
public static readonly SlotInfo ValueSlot = new SlotInfo("Value", canInlineInto: true);
ILInstruction value;
public ILInstruction Value {
get { return this.value; }
set {
ValidateChild(value);
SetChildInstruction(ref this.value, value, 1);
}
}
protected sealed override int GetChildCount()
{
return 2;
}
protected sealed override ILInstruction GetChild(int index)
{
switch (index) {
case 0:
return this.target;
case 1:
return this.value;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override void SetChild(int index, ILInstruction value)
{
switch (index) {
case 0:
this.Target = value;
break;
case 1:
this.Value = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override SlotInfo GetChildSlot(int index)
{
switch (index) {
case 0:
return TargetSlot;
case 1:
return ValueSlot;
default:
throw new IndexOutOfRangeException();
}
}
public sealed override ILInstruction Clone()
{
var clone = (CompoundAssignmentInstruction)ShallowClone();
clone.Target = this.target.Clone();
clone.Value = this.value.Clone();
return clone;
}
protected override InstructionFlags ComputeFlags()
{
return target.Flags | value.Flags;
}
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.None;
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
ILRange.WriteTo(output, options);
output.Write(OpCode);
output.Write('(');
this.target.WriteTo(output, options);
output.Write(", ");
this.value.WriteTo(output, options);
output.Write(')');
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Represents invalid IL. Semantically, this instruction is considered to throw some kind of exception.</summary>
public sealed partial class InvalidBranch : SimpleInstruction
@ -891,96 +983,66 @@ namespace ICSharpCode.Decompiler.IL
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Common instruction for compound assignments.</summary>
public sealed partial class CompoundAssignmentInstruction : ILInstruction
/// <summary>Common instruction for numeric compound assignments.</summary>
public sealed partial class NumericCompoundAssign : CompoundAssignmentInstruction
{
public static readonly SlotInfo TargetSlot = new SlotInfo("Target", canInlineInto: true);
ILInstruction target;
public ILInstruction Target {
get { return this.target; }
set {
ValidateChild(value);
SetChildInstruction(ref this.target, value, 0);
}
}
public static readonly SlotInfo ValueSlot = new SlotInfo("Value", canInlineInto: true);
ILInstruction value;
public ILInstruction Value {
get { return this.value; }
set {
ValidateChild(value);
SetChildInstruction(ref this.value, value, 1);
}
IType type;
/// <summary>Returns the type operand.</summary>
public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
protected sealed override int GetChildCount()
public override StackType ResultType { get { return type.GetStackType(); } }
public override void AcceptVisitor(ILVisitor visitor)
{
return 2;
visitor.VisitNumericCompoundAssign(this);
}
protected sealed override ILInstruction GetChild(int index)
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
switch (index) {
case 0:
return this.target;
case 1:
return this.value;
default:
throw new IndexOutOfRangeException();
}
return visitor.VisitNumericCompoundAssign(this);
}
protected sealed override void SetChild(int index, ILInstruction value)
public override T AcceptVisitor<C, T>(ILVisitor<C, T> visitor, C context)
{
switch (index) {
case 0:
this.Target = value;
break;
case 1:
this.Value = value;
break;
default:
throw new IndexOutOfRangeException();
}
return visitor.VisitNumericCompoundAssign(this, context);
}
protected sealed override SlotInfo GetChildSlot(int index)
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
switch (index) {
case 0:
return TargetSlot;
case 1:
return ValueSlot;
default:
throw new IndexOutOfRangeException();
}
var o = other as NumericCompoundAssign;
return o != null && type.Equals(o.type) && CheckForOverflow == o.CheckForOverflow && Sign == o.Sign && Operator == o.Operator && Target.PerformMatch(o.Target, ref match) && Value.PerformMatch(o.Value, ref match);
}
public sealed override ILInstruction Clone()
}
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Common instruction for user-defined compound assignments.</summary>
public sealed partial class UserDefinedCompoundAssign : CompoundAssignmentInstruction
{
protected override InstructionFlags ComputeFlags()
{
var clone = (CompoundAssignmentInstruction)ShallowClone();
clone.Target = this.target.Clone();
clone.Value = this.value.Clone();
return clone;
return base.ComputeFlags() | InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
IType type;
/// <summary>Returns the type operand.</summary>
public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags | InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
}
public override StackType ResultType { get { return type.GetStackType(); } }
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitCompoundAssignmentInstruction(this);
visitor.VisitUserDefinedCompoundAssign(this);
}
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitCompoundAssignmentInstruction(this);
return visitor.VisitUserDefinedCompoundAssign(this);
}
public override T AcceptVisitor<C, T>(ILVisitor<C, T> visitor, C context)
{
return visitor.VisitCompoundAssignmentInstruction(this, context);
return visitor.VisitUserDefinedCompoundAssign(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as CompoundAssignmentInstruction;
return o != null && this.target.PerformMatch(o.target, ref match) && this.value.PerformMatch(o.value, ref match) && type.Equals(o.type) && CheckForOverflow == o.CheckForOverflow && Sign == o.Sign && Operator == o.Operator;
var o = other as UserDefinedCompoundAssign;
return o != null && this.Method.Equals(o.Method) && this.CompoundAssignmentType == o.CompoundAssignmentType && Target.PerformMatch(o.Target, ref match) && Value.PerformMatch(o.Value, ref match);
}
}
}
@ -5099,7 +5161,11 @@ namespace ICSharpCode.Decompiler.IL
{
Default(inst);
}
protected internal virtual void VisitCompoundAssignmentInstruction(CompoundAssignmentInstruction inst)
protected internal virtual void VisitNumericCompoundAssign(NumericCompoundAssign inst)
{
Default(inst);
}
protected internal virtual void VisitUserDefinedCompoundAssign(UserDefinedCompoundAssign inst)
{
Default(inst);
}
@ -5417,7 +5483,11 @@ namespace ICSharpCode.Decompiler.IL
{
return Default(inst);
}
protected internal virtual T VisitCompoundAssignmentInstruction(CompoundAssignmentInstruction inst)
protected internal virtual T VisitNumericCompoundAssign(NumericCompoundAssign inst)
{
return Default(inst);
}
protected internal virtual T VisitUserDefinedCompoundAssign(UserDefinedCompoundAssign inst)
{
return Default(inst);
}
@ -5735,7 +5805,11 @@ namespace ICSharpCode.Decompiler.IL
{
return Default(inst, context);
}
protected internal virtual T VisitCompoundAssignmentInstruction(CompoundAssignmentInstruction inst, C context)
protected internal virtual T VisitNumericCompoundAssign(NumericCompoundAssign inst, C context)
{
return Default(inst, context);
}
protected internal virtual T VisitUserDefinedCompoundAssign(UserDefinedCompoundAssign inst, C context)
{
return Default(inst, context);
}
@ -6024,7 +6098,8 @@ namespace ICSharpCode.Decompiler.IL
"Block",
"PinnedRegion",
"binary",
"compound",
"numeric.compound",
"user.compound",
"bit.not",
"arglist",
"br",

21
ICSharpCode.Decompiler/IL/Instructions.tt

@ -33,7 +33,9 @@
new OpCode("CallInstruction", "Instruction with a list of arguments.",
AbstractBaseClass, CustomChildren(new []{ new ArgumentInfo("arguments") { IsCollection = true }}),
CustomWriteTo, MayThrow, SideEffect),
new OpCode("PatternInstruction", "Base class for pattern matching in ILAst.", AbstractBaseClass, ResultType("Unknown")) { Namespace = "ICSharpCode.Decompiler.IL.Patterns" }
new OpCode("PatternInstruction", "Base class for pattern matching in ILAst.", AbstractBaseClass, ResultType("Unknown")) { Namespace = "ICSharpCode.Decompiler.IL.Patterns" },
new OpCode("CompoundAssignmentInstruction", "Common instruction for compound assignments.",
AbstractBaseClass, CustomConstructor, CustomArguments(("target", null), ("value", null))),
};
OpCode[] opCodes = {
@ -66,10 +68,19 @@
new OpCode("binary", "Common instruction for add, sub, mul, div, rem, bit.and, bit.or, bit.xor, shl and shr.",
CustomClassName("BinaryNumericInstruction"), Binary, CustomWriteTo, CustomConstructor, CustomComputeFlags,
MatchCondition("CheckForOverflow == o.CheckForOverflow && Sign == o.Sign && Operator == o.Operator && IsLifted == o.IsLifted")),
new OpCode("compound", "Common instruction for compound assignments.",
CustomClassName("CompoundAssignmentInstruction"), CustomConstructor, CustomComputeFlags,
MayThrow, CustomArguments(("target", null), ("value", null)), HasTypeOperand, ResultType("type.GetStackType()"), CustomWriteTo,
MatchCondition("CheckForOverflow == o.CheckForOverflow && Sign == o.Sign && Operator == o.Operator")),
new OpCode("numeric.compound", "Common instruction for numeric compound assignments.",
CustomClassName("NumericCompoundAssign"), BaseClass("CompoundAssignmentInstruction"), CustomConstructor, CustomComputeFlags,
MayThrow, HasTypeOperand, ResultType("type.GetStackType()"), CustomWriteTo,
MatchCondition("CheckForOverflow == o.CheckForOverflow && Sign == o.Sign && Operator == o.Operator"),
MatchCondition("Target.PerformMatch(o.Target, ref match)"),
MatchCondition("Value.PerformMatch(o.Value, ref match)")),
new OpCode("user.compound", "Common instruction for user-defined compound assignments.",
CustomClassName("UserDefinedCompoundAssign"), BaseClass("CompoundAssignmentInstruction"), CustomConstructor,
MayThrow, SideEffect, CustomWriteTo,
MatchCondition("this.Method.Equals(o.Method)"),
MatchCondition("this.CompoundAssignmentType == o.CompoundAssignmentType"),
MatchCondition("Target.PerformMatch(o.Target, ref match)"),
MatchCondition("Value.PerformMatch(o.Value, ref match)")),
new OpCode("bit.not", "Bitwise NOT", Unary, CustomConstructor, MatchCondition("IsLifted == o.IsLifted && UnderlyingResultType == o.UnderlyingResultType")),
new OpCode("arglist", "Retrieves the RuntimeArgumentHandle.", NoArguments, ResultType("O")),
new OpCode("br", "Unconditional branch. <c>goto target;</c>",

91
ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs

@ -28,7 +28,35 @@ namespace ICSharpCode.Decompiler.IL
EvaluatesToNewValue
}
public partial class CompoundAssignmentInstruction : ILInstruction
public abstract partial class CompoundAssignmentInstruction : ILInstruction
{
public readonly CompoundAssignmentType CompoundAssignmentType;
public CompoundAssignmentInstruction(OpCode opCode, CompoundAssignmentType compoundAssignmentType, ILInstruction target, ILInstruction value)
: base(opCode)
{
this.CompoundAssignmentType = compoundAssignmentType;
this.Target = target;
this.Value = value;
}
internal static bool IsValidCompoundAssignmentTarget(ILInstruction inst)
{
switch (inst.OpCode) {
// case OpCode.LdLoc: -- not valid -- does not mark the variable as written to
case OpCode.LdObj:
return true;
case OpCode.Call:
case OpCode.CallVirt:
var owner = ((CallInstruction)inst).Method.AccessorOwner as IProperty;
return owner != null && owner.CanSet;
default:
return false;
}
}
}
public partial class NumericCompoundAssign : CompoundAssignmentInstruction
{
/// <summary>
/// Gets whether the instruction checks for overflow.
@ -50,13 +78,11 @@ namespace ICSharpCode.Decompiler.IL
/// The operator used by this assignment operator instruction.
/// </summary>
public readonly BinaryNumericOperator Operator;
public readonly CompoundAssignmentType CompoundAssignmentType;
public bool IsLifted { get; }
public CompoundAssignmentInstruction(BinaryNumericInstruction binary, ILInstruction target, ILInstruction value, IType type, CompoundAssignmentType compoundAssignmentType)
: base(OpCode.CompoundAssignmentInstruction)
public NumericCompoundAssign(BinaryNumericInstruction binary, ILInstruction target, ILInstruction value, IType type, CompoundAssignmentType compoundAssignmentType)
: base(OpCode.NumericCompoundAssign, compoundAssignmentType, target, value)
{
Debug.Assert(IsBinaryCompatibleWithType(binary, type));
this.CheckForOverflow = binary.CheckForOverflow;
@ -65,11 +91,8 @@ namespace ICSharpCode.Decompiler.IL
this.RightInputType = binary.RightInputType;
this.UnderlyingResultType = binary.UnderlyingResultType;
this.Operator = binary.Operator;
this.CompoundAssignmentType = compoundAssignmentType;
this.IsLifted = binary.IsLifted;
this.Target = target;
this.type = type;
this.Value = value;
this.ILRange = binary.ILRange;
Debug.Assert(compoundAssignmentType == CompoundAssignmentType.EvaluatesToNewValue || (Operator == BinaryNumericOperator.Add || Operator == BinaryNumericOperator.Sub));
Debug.Assert(IsValidCompoundAssignmentTarget(Target));
@ -127,24 +150,9 @@ namespace ICSharpCode.Decompiler.IL
return true;
}
internal static bool IsValidCompoundAssignmentTarget(ILInstruction inst)
{
switch (inst.OpCode) {
// case OpCode.LdLoc: -- not valid -- does not mark the variable as written to
case OpCode.LdObj:
return true;
case OpCode.Call:
case OpCode.CallVirt:
var owner = ((CallInstruction)inst).Method.AccessorOwner as IProperty;
return owner != null && owner.CanSet;
default:
return false;
}
}
protected override InstructionFlags ComputeFlags()
{
var flags = target.Flags | value.Flags | InstructionFlags.SideEffect;
var flags = Target.Flags | Value.Flags | InstructionFlags.SideEffect;
if (CheckForOverflow || (Operator == BinaryNumericOperator.Div || Operator == BinaryNumericOperator.Rem))
flags |= InstructionFlags.MayThrow;
return flags;
@ -181,6 +189,41 @@ namespace ICSharpCode.Decompiler.IL
output.Write(')');
}
}
public partial class UserDefinedCompoundAssign : CompoundAssignmentInstruction
{
public readonly IMethod Method;
public readonly bool IsLifted;
public UserDefinedCompoundAssign(IMethod method, CompoundAssignmentType compoundAssignmentType, ILInstruction target, ILInstruction value, bool isLifted)
: base(OpCode.UserDefinedCompoundAssign, compoundAssignmentType, target, value)
{
this.Method = method;
this.IsLifted = isLifted;
Debug.Assert(Method.IsOperator);
Debug.Assert(compoundAssignmentType == CompoundAssignmentType.EvaluatesToNewValue || (Method.Name == "op_Increment" || Method.Name == "op_Decrement"));
Debug.Assert(IsValidCompoundAssignmentTarget(Target));
}
public override StackType ResultType => Method.ReturnType.GetStackType();
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
ILRange.WriteTo(output, options);
output.Write(OpCode);
if (CompoundAssignmentType == CompoundAssignmentType.EvaluatesToNewValue)
output.Write(".new");
else
output.Write(".old");
output.Write(' ');
Method.WriteTo(output);
output.Write('(');
this.Target.WriteTo(output, options);
output.Write(", ");
this.Value.WriteTo(output, options);
output.Write(')');
}
}
}

4
ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs

@ -321,9 +321,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
}
protected internal override void VisitCompoundAssignmentInstruction(CompoundAssignmentInstruction inst)
protected internal override void VisitNumericCompoundAssign(NumericCompoundAssign inst)
{
base.VisitCompoundAssignmentInstruction(inst);
base.VisitNumericCompoundAssign(inst);
if (inst.Target.MatchLdLoc(out var v)) {
inst.ReplaceWith(new StLoc(v, new BinaryNumericInstruction(inst.Operator, inst.Target, inst.Value, inst.CheckForOverflow, inst.Sign)));
}

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

@ -241,14 +241,20 @@ namespace ICSharpCode.Decompiler.IL.Transforms
expr.AcceptVisitor(this);
} else {
base.VisitCall(inst);
TransformAssignment.HandleCallCompoundAssign(inst, context);
if (TransformAssignment.HandleCallCompoundAssign(inst, context))
return;
if (TransformAssignment.HandleUserDefinedCompoundAssignOnCall(inst, context))
return;
}
}
protected internal override void VisitCallVirt(CallVirt inst)
{
base.VisitCallVirt(inst);
TransformAssignment.HandleCallCompoundAssign(inst, context);
if (TransformAssignment.HandleCallCompoundAssign(inst, context))
return;
if (TransformAssignment.HandleUserDefinedCompoundAssignOnCall(inst, context))
return;
}
protected internal override void VisitNewObj(NewObj inst)
@ -301,7 +307,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms
context.RequestRerun();
return;
}
TransformAssignment.HandleStObjCompoundAssign(inst, context);
if (TransformAssignment.HandleStObjCompoundAssign(inst, context)) {
context.RequestRerun();
return;
}
if (TransformAssignment.HandleUserDefinedCompoundAssignOnReference(inst, context)) {
context.RequestRerun();
return;
}
}
protected internal override void VisitIfInstruction(IfInstruction inst)

3
ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs

@ -451,7 +451,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
case OpCode.NewObj:
case OpCode.StLoc:
case OpCode.StObj:
case OpCode.CompoundAssignmentInstruction:
case OpCode.NumericCompoundAssign:
case OpCode.UserDefinedCompoundAssign:
return true;
default:
return false;

3
ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs

@ -296,7 +296,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
switch (inlinedExpression.OpCode) {
case OpCode.DefaultValue:
case OpCode.StObj:
case OpCode.CompoundAssignmentInstruction:
case OpCode.NumericCompoundAssign:
case OpCode.UserDefinedCompoundAssign:
case OpCode.Await:
return true;
case OpCode.LdLoc:

Loading…
Cancel
Save