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 @@ -699,7 +699,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Adds two numbers.</summary>
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 @@ -716,7 +716,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Subtracts two numbers</summary>
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 @@ -733,7 +733,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Multiplies two numbers</summary>
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 @@ -750,7 +750,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Divides two numbers</summary>
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 @@ -776,7 +776,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Division remainder</summary>
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 @@ -802,7 +802,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Bitwise AND</summary>
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 @@ -819,7 +819,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Bitwise OR</summary>
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 @@ -836,7 +836,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Bitwise XOR</summary>
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 @@ -1842,7 +1842,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Shift left</summary>
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 @@ -1859,7 +1859,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Shift right</summary>
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 @@ -3896,29 +3896,29 @@ namespace ICSharpCode.Decompiler.IL
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) {
case OpCode.Add:
return new Add(left, right, checkForOverflow, sign, compoundAssignmentType);
return new Add(left, right, checkForOverflow, sign);
case OpCode.Sub:
return new Sub(left, right, checkForOverflow, sign, compoundAssignmentType);
return new Sub(left, right, checkForOverflow, sign);
case OpCode.Mul:
return new Mul(left, right, checkForOverflow, sign, compoundAssignmentType);
return new Mul(left, right, checkForOverflow, sign);
case OpCode.Div:
return new Div(left, right, checkForOverflow, sign, compoundAssignmentType);
return new Div(left, right, checkForOverflow, sign);
case OpCode.Rem:
return new Rem(left, right, checkForOverflow, sign, compoundAssignmentType);
return new Rem(left, right, checkForOverflow, sign);
case OpCode.BitAnd:
return new BitAnd(left, right, checkForOverflow, sign, compoundAssignmentType);
return new BitAnd(left, right, checkForOverflow, sign);
case OpCode.BitOr:
return new BitOr(left, right, checkForOverflow, sign, compoundAssignmentType);
return new BitOr(left, right, checkForOverflow, sign);
case OpCode.BitXor:
return new BitXor(left, right, checkForOverflow, sign, compoundAssignmentType);
return new BitXor(left, right, checkForOverflow, sign);
case OpCode.Shl:
return new Shl(left, right, checkForOverflow, sign, compoundAssignmentType);
return new Shl(left, right, checkForOverflow, sign);
case OpCode.Shr:
return new Shr(left, right, checkForOverflow, sign, compoundAssignmentType);
return new Shr(left, right, checkForOverflow, sign);
default:
throw new ArgumentException("opCode is not a binary numeric instruction");
}

6
ICSharpCode.Decompiler/IL/Instructions.tt

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

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

@ -33,11 +33,6 @@ namespace ICSharpCode.Decompiler.IL @@ -33,11 +33,6 @@ namespace ICSharpCode.Decompiler.IL
public abstract partial class BinaryNumericInstruction : BinaryInstruction
{
/// <summary>
/// Gets whether this instruction is a compound assignment.
/// </summary>
public readonly CompoundAssignmentType CompoundAssignmentType;
/// <summary>
/// Gets whether the instruction checks for overflow.
/// </summary>
@ -52,15 +47,14 @@ namespace ICSharpCode.Decompiler.IL @@ -52,15 +47,14 @@ namespace ICSharpCode.Decompiler.IL
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)
{
this.CheckForOverflow = checkForOverflow;
this.Sign = sign;
this.CompoundAssignmentType = compoundAssignmentType;
this.resultType = ComputeResultType(opCode, left.ResultType, right.ResultType);
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)
@ -108,54 +102,16 @@ namespace ICSharpCode.Decompiler.IL @@ -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()
{
var flags = base.ComputeFlags();
if (CheckForOverflow)
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;
}
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);
if (CheckForOverflow)
output.Write(".ovf");

Loading…
Cancel
Save