Browse Source

Remove CompoundAssignmentType from BinaryNumericInstruction:

Compound assignments were not supported by any user of the ILAst.
In particular, they are problematic because they are yet another way to store to a local variable (making reaching definitions complex).
They also didn't update the StoreCount correctly when inst.Left or inst.Left.Variable was changed.

Since they weren't used (yet), just remove them.
Hopefully we'll find a better representation once we need compound assignments.
pull/728/head
Daniel Grunwald 9 years ago
parent
commit
55d953b889
  1. 42
      ICSharpCode.Decompiler/IL/Instructions.cs
  2. 6
      ICSharpCode.Decompiler/IL/Instructions.tt
  3. 48
      ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs

42
ICSharpCode.Decompiler/IL/Instructions.cs

@ -699,7 +699,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Adds two numbers.</summary> /// <summary>Adds two numbers.</summary>
public sealed partial class Add : BinaryNumericInstruction public sealed partial class Add : BinaryNumericInstruction
{ {
public Add(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) : base(OpCode.Add, left, right, checkForOverflow, sign, compoundAssignmentType) public Add(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.Add, left, right, checkForOverflow, sign)
{ {
} }
@ -716,7 +716,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Subtracts two numbers</summary> /// <summary>Subtracts two numbers</summary>
public sealed partial class Sub : BinaryNumericInstruction public sealed partial class Sub : BinaryNumericInstruction
{ {
public Sub(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) : base(OpCode.Sub, left, right, checkForOverflow, sign, compoundAssignmentType) public Sub(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.Sub, left, right, checkForOverflow, sign)
{ {
} }
@ -733,7 +733,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Multiplies two numbers</summary> /// <summary>Multiplies two numbers</summary>
public sealed partial class Mul : BinaryNumericInstruction public sealed partial class Mul : BinaryNumericInstruction
{ {
public Mul(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) : base(OpCode.Mul, left, right, checkForOverflow, sign, compoundAssignmentType) public Mul(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.Mul, left, right, checkForOverflow, sign)
{ {
} }
@ -750,7 +750,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Divides two numbers</summary> /// <summary>Divides two numbers</summary>
public sealed partial class Div : BinaryNumericInstruction public sealed partial class Div : BinaryNumericInstruction
{ {
public Div(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) : base(OpCode.Div, left, right, checkForOverflow, sign, compoundAssignmentType) public Div(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.Div, left, right, checkForOverflow, sign)
{ {
} }
@ -776,7 +776,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Division remainder</summary> /// <summary>Division remainder</summary>
public sealed partial class Rem : BinaryNumericInstruction public sealed partial class Rem : BinaryNumericInstruction
{ {
public Rem(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) : base(OpCode.Rem, left, right, checkForOverflow, sign, compoundAssignmentType) public Rem(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.Rem, left, right, checkForOverflow, sign)
{ {
} }
@ -802,7 +802,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Bitwise AND</summary> /// <summary>Bitwise AND</summary>
public sealed partial class BitAnd : BinaryNumericInstruction public sealed partial class BitAnd : BinaryNumericInstruction
{ {
public BitAnd(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) : base(OpCode.BitAnd, left, right, checkForOverflow, sign, compoundAssignmentType) public BitAnd(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.BitAnd, left, right, checkForOverflow, sign)
{ {
} }
@ -819,7 +819,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Bitwise OR</summary> /// <summary>Bitwise OR</summary>
public sealed partial class BitOr : BinaryNumericInstruction public sealed partial class BitOr : BinaryNumericInstruction
{ {
public BitOr(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) : base(OpCode.BitOr, left, right, checkForOverflow, sign, compoundAssignmentType) public BitOr(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.BitOr, left, right, checkForOverflow, sign)
{ {
} }
@ -836,7 +836,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Bitwise XOR</summary> /// <summary>Bitwise XOR</summary>
public sealed partial class BitXor : BinaryNumericInstruction public sealed partial class BitXor : BinaryNumericInstruction
{ {
public BitXor(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) : base(OpCode.BitXor, left, right, checkForOverflow, sign, compoundAssignmentType) public BitXor(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.BitXor, left, right, checkForOverflow, sign)
{ {
} }
@ -1842,7 +1842,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Shift left</summary> /// <summary>Shift left</summary>
public sealed partial class Shl : BinaryNumericInstruction public sealed partial class Shl : BinaryNumericInstruction
{ {
public Shl(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) : base(OpCode.Shl, left, right, checkForOverflow, sign, compoundAssignmentType) public Shl(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.Shl, left, right, checkForOverflow, sign)
{ {
} }
@ -1859,7 +1859,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Shift right</summary> /// <summary>Shift right</summary>
public sealed partial class Shr : BinaryNumericInstruction public sealed partial class Shr : BinaryNumericInstruction
{ {
public Shr(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) : base(OpCode.Shr, left, right, checkForOverflow, sign, compoundAssignmentType) public Shr(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.Shr, left, right, checkForOverflow, sign)
{ {
} }
@ -3896,29 +3896,29 @@ namespace ICSharpCode.Decompiler.IL
partial class BinaryNumericInstruction partial class BinaryNumericInstruction
{ {
public static BinaryNumericInstruction Create(OpCode opCode, ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) public static BinaryNumericInstruction Create(OpCode opCode, ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign)
{ {
switch (opCode) { switch (opCode) {
case OpCode.Add: case OpCode.Add:
return new Add(left, right, checkForOverflow, sign, compoundAssignmentType); return new Add(left, right, checkForOverflow, sign);
case OpCode.Sub: case OpCode.Sub:
return new Sub(left, right, checkForOverflow, sign, compoundAssignmentType); return new Sub(left, right, checkForOverflow, sign);
case OpCode.Mul: case OpCode.Mul:
return new Mul(left, right, checkForOverflow, sign, compoundAssignmentType); return new Mul(left, right, checkForOverflow, sign);
case OpCode.Div: case OpCode.Div:
return new Div(left, right, checkForOverflow, sign, compoundAssignmentType); return new Div(left, right, checkForOverflow, sign);
case OpCode.Rem: case OpCode.Rem:
return new Rem(left, right, checkForOverflow, sign, compoundAssignmentType); return new Rem(left, right, checkForOverflow, sign);
case OpCode.BitAnd: case OpCode.BitAnd:
return new BitAnd(left, right, checkForOverflow, sign, compoundAssignmentType); return new BitAnd(left, right, checkForOverflow, sign);
case OpCode.BitOr: case OpCode.BitOr:
return new BitOr(left, right, checkForOverflow, sign, compoundAssignmentType); return new BitOr(left, right, checkForOverflow, sign);
case OpCode.BitXor: case OpCode.BitXor:
return new BitXor(left, right, checkForOverflow, sign, compoundAssignmentType); return new BitXor(left, right, checkForOverflow, sign);
case OpCode.Shl: case OpCode.Shl:
return new Shl(left, right, checkForOverflow, sign, compoundAssignmentType); return new Shl(left, right, checkForOverflow, sign);
case OpCode.Shr: case OpCode.Shr:
return new Shr(left, right, checkForOverflow, sign, compoundAssignmentType); return new Shr(left, right, checkForOverflow, sign);
default: default:
throw new ArgumentException("opCode is not a binary numeric instruction"); throw new ArgumentException("opCode is not a binary numeric instruction");
} }

6
ICSharpCode.Decompiler/IL/Instructions.tt

@ -303,12 +303,12 @@ namespace ICSharpCode.Decompiler.IL
partial class BinaryNumericInstruction partial class BinaryNumericInstruction
{ {
public static BinaryNumericInstruction Create(OpCode opCode, ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) public static BinaryNumericInstruction Create(OpCode opCode, ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign)
{ {
switch (opCode) { switch (opCode) {
<# foreach (OpCode opCode in opCodes.Where(c => c.BaseClass == "BinaryNumericInstruction")) { #> <# foreach (OpCode opCode in opCodes.Where(c => c.BaseClass == "BinaryNumericInstruction")) { #>
case OpCode.<#=opCode.Name#>: case OpCode.<#=opCode.Name#>:
return new <#=opCode.Name#>(left, right, checkForOverflow, sign, compoundAssignmentType); return new <#=opCode.Name#>(left, right, checkForOverflow, sign);
<# } #> <# } #>
default: default:
throw new ArgumentException("opCode is not a binary numeric instruction"); throw new ArgumentException("opCode is not a binary numeric instruction");
@ -581,8 +581,6 @@ namespace ICSharpCode.Decompiler.IL
opCode.BaseConstructorArguments.Add("checkForOverflow"); opCode.BaseConstructorArguments.Add("checkForOverflow");
opCode.ConstructorParameters.Add("Sign sign"); opCode.ConstructorParameters.Add("Sign sign");
opCode.BaseConstructorArguments.Add("sign"); opCode.BaseConstructorArguments.Add("sign");
opCode.ConstructorParameters.Add("CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None");
opCode.BaseConstructorArguments.Add("compoundAssignmentType");
}; };
static Action<OpCode> CustomArguments(params string[] arguments) static Action<OpCode> CustomArguments(params string[] arguments)

48
ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs

@ -33,11 +33,6 @@ namespace ICSharpCode.Decompiler.IL
public abstract partial class BinaryNumericInstruction : BinaryInstruction public abstract partial class BinaryNumericInstruction : BinaryInstruction
{ {
/// <summary>
/// Gets whether this instruction is a compound assignment.
/// </summary>
public readonly CompoundAssignmentType CompoundAssignmentType;
/// <summary> /// <summary>
/// Gets whether the instruction checks for overflow. /// Gets whether the instruction checks for overflow.
/// </summary> /// </summary>
@ -52,15 +47,14 @@ namespace ICSharpCode.Decompiler.IL
readonly StackType resultType; readonly StackType resultType;
protected BinaryNumericInstruction(OpCode opCode, ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType) protected BinaryNumericInstruction(OpCode opCode, ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign)
: base(opCode, left, right) : base(opCode, left, right)
{ {
this.CheckForOverflow = checkForOverflow; this.CheckForOverflow = checkForOverflow;
this.Sign = sign; this.Sign = sign;
this.CompoundAssignmentType = compoundAssignmentType;
this.resultType = ComputeResultType(opCode, left.ResultType, right.ResultType); this.resultType = ComputeResultType(opCode, left.ResultType, right.ResultType);
Debug.Assert(resultType != StackType.Unknown); Debug.Assert(resultType != StackType.Unknown);
Debug.Assert(CompoundAssignmentType == CompoundAssignmentType.None || IsValidCompoundAssignmentTarget(Left)); //Debug.Assert(CompoundAssignmentType == CompoundAssignmentType.None || IsValidCompoundAssignmentTarget(Left));
} }
internal static bool IsValidCompoundAssignmentTarget(ILInstruction inst) internal static bool IsValidCompoundAssignmentTarget(ILInstruction inst)
@ -108,54 +102,16 @@ namespace ICSharpCode.Decompiler.IL
} }
} }
internal override void CheckInvariant(ILPhase phase)
{
base.CheckInvariant(phase);
Debug.Assert(CompoundAssignmentType == CompoundAssignmentType.None || IsValidCompoundAssignmentTarget(Left));
}
protected override void Connected()
{
base.Connected();
// Count the local variable store due to the compound assignment:
ILVariable v;
if (CompoundAssignmentType != CompoundAssignmentType.None && Left.MatchLdLoc(out v)) {
v.StoreCount++;
}
}
protected override void Disconnected()
{
base.Disconnected();
// Count the local variable store due to the compound assignment:
ILVariable v;
if (CompoundAssignmentType != CompoundAssignmentType.None && Left.MatchLdLoc(out v)) {
v.StoreCount--;
}
}
protected override InstructionFlags ComputeFlags() protected override InstructionFlags ComputeFlags()
{ {
var flags = base.ComputeFlags(); var flags = base.ComputeFlags();
if (CheckForOverflow) if (CheckForOverflow)
flags |= InstructionFlags.MayThrow; flags |= InstructionFlags.MayThrow;
// Set MayWriteLocals if this is a compound assignment to a local variable
if (CompoundAssignmentType != CompoundAssignmentType.None && Left.OpCode == OpCode.LdLoc)
flags |= InstructionFlags.MayWriteLocals;
return flags; return flags;
} }
public override void WriteTo(ITextOutput output) public override void WriteTo(ITextOutput output)
{ {
switch (CompoundAssignmentType) {
case CompoundAssignmentType.EvaluatesToNewValue:
output.Write("compound.assign");
break;
case CompoundAssignmentType.EvaluatesToOldValue:
output.Write("compound.assign.oldvalue");
break;
}
output.Write(OpCode); output.Write(OpCode);
if (CheckForOverflow) if (CheckForOverflow)
output.Write(".ovf"); output.Write(".ovf");

Loading…
Cancel
Save