diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
index 2109bad73..a90ab5c00 100644
--- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
+++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
@@ -474,44 +474,32 @@ namespace ICSharpCode.Decompiler.CSharp
.WithRR(new OperatorResolveResult(left.Type, ExpressionType.Assign, left.ResolveResult, right.ResolveResult));
}
- protected internal override TranslatedExpression VisitAdd(Add inst)
- {
- return HandleBinaryNumeric(inst, BinaryOperatorType.Add);
- }
-
- protected internal override TranslatedExpression VisitSub(Sub inst)
- {
- return HandleBinaryNumeric(inst, BinaryOperatorType.Subtract);
- }
-
- protected internal override TranslatedExpression VisitMul(Mul inst)
- {
- return HandleBinaryNumeric(inst, BinaryOperatorType.Multiply);
- }
-
- protected internal override TranslatedExpression VisitDiv(Div inst)
- {
- return HandleBinaryNumeric(inst, BinaryOperatorType.Divide);
- }
-
- protected internal override TranslatedExpression VisitRem(Rem inst)
- {
- return HandleBinaryNumeric(inst, BinaryOperatorType.Modulus);
- }
-
- protected internal override TranslatedExpression VisitBitXor(BitXor inst)
- {
- return HandleBinaryNumeric(inst, BinaryOperatorType.ExclusiveOr);
- }
-
- protected internal override TranslatedExpression VisitBitAnd(BitAnd inst)
- {
- return HandleBinaryNumeric(inst, BinaryOperatorType.BitwiseAnd);
- }
-
- protected internal override TranslatedExpression VisitBitOr(BitOr inst)
- {
- return HandleBinaryNumeric(inst, BinaryOperatorType.BitwiseOr);
+ protected internal override TranslatedExpression VisitBinaryNumericInstruction(BinaryNumericInstruction inst)
+ {
+ switch (inst.Operator) {
+ case BinaryNumericOperator.Add:
+ return HandleBinaryNumeric(inst, BinaryOperatorType.Add);
+ case BinaryNumericOperator.Sub:
+ return HandleBinaryNumeric(inst, BinaryOperatorType.Subtract);
+ case BinaryNumericOperator.Mul:
+ return HandleBinaryNumeric(inst, BinaryOperatorType.Multiply);
+ case BinaryNumericOperator.Div:
+ return HandleBinaryNumeric(inst, BinaryOperatorType.Divide);
+ case BinaryNumericOperator.Rem:
+ return HandleBinaryNumeric(inst, BinaryOperatorType.Modulus);
+ case BinaryNumericOperator.BitAnd:
+ return HandleBinaryNumeric(inst, BinaryOperatorType.BitwiseAnd);
+ case BinaryNumericOperator.BitOr:
+ return HandleBinaryNumeric(inst, BinaryOperatorType.BitwiseOr);
+ case BinaryNumericOperator.BitXor:
+ return HandleBinaryNumeric(inst, BinaryOperatorType.ExclusiveOr);
+ case BinaryNumericOperator.ShiftLeft:
+ return HandleShift(inst, BinaryOperatorType.ShiftLeft);
+ case BinaryNumericOperator.ShiftRight:
+ return HandleShift(inst, BinaryOperatorType.ShiftRight);
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
}
TranslatedExpression HandleBinaryNumeric(BinaryNumericInstruction inst, BinaryOperatorType op)
@@ -583,16 +571,6 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
- protected internal override TranslatedExpression VisitShl(Shl inst)
- {
- return HandleShift(inst, BinaryOperatorType.ShiftLeft);
- }
-
- protected internal override TranslatedExpression VisitShr(Shr inst)
- {
- return HandleShift(inst, BinaryOperatorType.ShiftRight);
- }
-
TranslatedExpression HandleShift(BinaryNumericInstruction inst, BinaryOperatorType op)
{
var left = Translate(inst.Left);
diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs b/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs
index 743455711..6485990ed 100644
--- a/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs
+++ b/ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs
@@ -436,7 +436,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
ILInstruction left, right, value;
return block.Instructions.Count == 2
&& block.Instructions[0].MatchStLoc(nativeVar, out value)
- && value.MatchAdd(out left, out right)
+ && value.MatchBinaryNumericInstruction(BinaryNumericOperator.Add, out left, out right)
&& left.MatchLdLoc(nativeVar)
&& IsOffsetToStringDataCall(right)
&& block.Instructions[1].MatchBranch(targetBlock);
diff --git a/ICSharpCode.Decompiler/IL/ILReader.cs b/ICSharpCode.Decompiler/IL/ILReader.cs
index e4bf3d963..909553ceb 100644
--- a/ICSharpCode.Decompiler/IL/ILReader.cs
+++ b/ICSharpCode.Decompiler/IL/ILReader.cs
@@ -335,13 +335,13 @@ namespace ICSharpCode.Decompiler.IL
{
switch (PeekStackType()) {
case StackType.I4:
- return Push(new Sub(new LdcI4(0), Pop(), checkForOverflow: false, sign: Sign.None));
+ return Push(new BinaryNumericInstruction(BinaryNumericOperator.Sub, new LdcI4(0), Pop(), checkForOverflow: false, sign: Sign.None));
case StackType.I:
- return Push(new Sub(new Conv(new LdcI4(0), PrimitiveType.I, false, Sign.None), Pop(), checkForOverflow: false, sign: Sign.None));
+ return Push(new BinaryNumericInstruction(BinaryNumericOperator.Sub, new Conv(new LdcI4(0), PrimitiveType.I, false, Sign.None), Pop(), checkForOverflow: false, sign: Sign.None));
case StackType.I8:
- return Push(new Sub(new LdcI8(0), Pop(), checkForOverflow: false, sign: Sign.None));
+ return Push(new BinaryNumericInstruction(BinaryNumericOperator.Sub, new LdcI8(0), Pop(), checkForOverflow: false, sign: Sign.None));
case StackType.F:
- return Push(new Sub(new LdcF(0), Pop(), checkForOverflow: false, sign: Sign.None));
+ return Push(new BinaryNumericInstruction(BinaryNumericOperator.Sub, new LdcF(0), Pop(), checkForOverflow: false, sign: Sign.None));
default:
Warn("Unsupported input type for neg.");
goto case StackType.I4;
@@ -363,13 +363,13 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Volatile:
return DecodeVolatile();
case ILOpCode.Add:
- return BinaryNumeric(OpCode.Add);
+ return BinaryNumeric(BinaryNumericOperator.Add);
case ILOpCode.Add_Ovf:
- return BinaryNumeric(OpCode.Add, true, Sign.Signed);
+ return BinaryNumeric(BinaryNumericOperator.Add, true, Sign.Signed);
case ILOpCode.Add_Ovf_Un:
- return BinaryNumeric(OpCode.Add, true, Sign.Unsigned);
+ return BinaryNumeric(BinaryNumericOperator.Add, true, Sign.Unsigned);
case ILOpCode.And:
- return BinaryNumeric(OpCode.BitAnd);
+ return BinaryNumeric(BinaryNumericOperator.BitAnd);
case ILOpCode.Arglist:
return Push(new Arglist());
case ILOpCode.Beq:
@@ -513,9 +513,9 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Cpblk:
throw new NotImplementedException();
case ILOpCode.Div:
- return BinaryNumeric(OpCode.Div, false, Sign.Signed);
+ return BinaryNumeric(BinaryNumericOperator.Div, false, Sign.Signed);
case ILOpCode.Div_Un:
- return BinaryNumeric(OpCode.Div, false, Sign.Unsigned);
+ return BinaryNumeric(BinaryNumericOperator.Div, false, Sign.Unsigned);
case ILOpCode.Dup:
return Push(Peek());
case ILOpCode.Endfilter:
@@ -607,11 +607,11 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Localloc:
return Push(new LocAlloc(Pop()));
case ILOpCode.Mul:
- return BinaryNumeric(OpCode.Mul, false, Sign.None);
+ return BinaryNumeric(BinaryNumericOperator.Mul, false, Sign.None);
case ILOpCode.Mul_Ovf:
- return BinaryNumeric(OpCode.Mul, true, Sign.Signed);
+ return BinaryNumeric(BinaryNumericOperator.Mul, true, Sign.Signed);
case ILOpCode.Mul_Ovf_Un:
- return BinaryNumeric(OpCode.Mul, true, Sign.Unsigned);
+ return BinaryNumeric(BinaryNumericOperator.Mul, true, Sign.Unsigned);
case ILOpCode.Neg:
return Neg();
case ILOpCode.Newobj:
@@ -621,22 +621,22 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Not:
return Push(new BitNot(Pop()));
case ILOpCode.Or:
- return BinaryNumeric(OpCode.BitOr);
+ return BinaryNumeric(BinaryNumericOperator.BitOr);
case ILOpCode.Pop:
Pop();
return new Nop();
case ILOpCode.Rem:
- return BinaryNumeric(OpCode.Rem, false, Sign.Signed);
+ return BinaryNumeric(BinaryNumericOperator.Rem, false, Sign.Signed);
case ILOpCode.Rem_Un:
- return BinaryNumeric(OpCode.Rem, false, Sign.Unsigned);
+ return BinaryNumeric(BinaryNumericOperator.Rem, false, Sign.Unsigned);
case ILOpCode.Ret:
return Return();
case ILOpCode.Shl:
- return BinaryNumeric(OpCode.Shl, false, Sign.None);
+ return BinaryNumeric(BinaryNumericOperator.ShiftLeft, false, Sign.None);
case ILOpCode.Shr:
- return BinaryNumeric(OpCode.Shr, false, Sign.Signed);
+ return BinaryNumeric(BinaryNumericOperator.ShiftRight, false, Sign.Signed);
case ILOpCode.Shr_Un:
- return BinaryNumeric(OpCode.Shr, false, Sign.Unsigned);
+ return BinaryNumeric(BinaryNumericOperator.ShiftRight, false, Sign.Unsigned);
case ILOpCode.Starg:
return Starg(reader.ReadUInt16());
case ILOpCode.Starg_S:
@@ -667,15 +667,15 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Stloc_3:
return Stloc(ilOpCode - ILOpCode.Stloc_0);
case ILOpCode.Sub:
- return BinaryNumeric(OpCode.Sub, false, Sign.None);
+ return BinaryNumeric(BinaryNumericOperator.Sub, false, Sign.None);
case ILOpCode.Sub_Ovf:
- return BinaryNumeric(OpCode.Sub, true, Sign.Signed);
+ return BinaryNumeric(BinaryNumericOperator.Sub, true, Sign.Signed);
case ILOpCode.Sub_Ovf_Un:
- return BinaryNumeric(OpCode.Sub, true, Sign.Unsigned);
+ return BinaryNumeric(BinaryNumericOperator.Sub, true, Sign.Unsigned);
case ILOpCode.Switch:
return DecodeSwitch();
case ILOpCode.Xor:
- return BinaryNumeric(OpCode.BitXor);
+ return BinaryNumeric(BinaryNumericOperator.BitXor);
case ILOpCode.Box:
{
var type = ReadAndDecodeTypeReference();
@@ -1200,11 +1200,11 @@ namespace ICSharpCode.Decompiler.IL
return instr;
}
- ILInstruction BinaryNumeric(OpCode opCode, bool checkForOverflow = false, Sign sign = Sign.None)
+ ILInstruction BinaryNumeric(BinaryNumericOperator @operator, bool checkForOverflow = false, Sign sign = Sign.None)
{
var right = Pop();
var left = Pop();
- if (opCode != OpCode.Shl && opCode != OpCode.Shr) {
+ if (@operator != BinaryNumericOperator.ShiftLeft && @operator != BinaryNumericOperator.ShiftRight) {
// make the implicit I4->I conversion explicit:
if (left.ResultType == StackType.I4 && right.ResultType == StackType.I) {
left = new Conv(left, PrimitiveType.I, false, Sign.None);
@@ -1212,7 +1212,7 @@ namespace ICSharpCode.Decompiler.IL
right = new Conv(right, PrimitiveType.I, false, Sign.None);
}
}
- return Push(BinaryNumericInstruction.Create(opCode, left, right, checkForOverflow, sign));
+ return Push(new BinaryNumericInstruction(@operator, left, right, checkForOverflow, sign));
}
ILInstruction LdToken(IMetadataTokenProvider token)
diff --git a/ICSharpCode.Decompiler/IL/Instructions.cs b/ICSharpCode.Decompiler/IL/Instructions.cs
index 23715522b..099991e4f 100644
--- a/ICSharpCode.Decompiler/IL/Instructions.cs
+++ b/ICSharpCode.Decompiler/IL/Instructions.cs
@@ -43,22 +43,8 @@ namespace ICSharpCode.Decompiler.IL
PinnedRegion,
/// Unary operator that expects an input of type I4. Returns 1 (of type I4) if the input value is 0. Otherwise, returns 0 (of type I4).
LogicNot,
- /// Adds two numbers.
- Add,
- /// Subtracts two numbers
- Sub,
- /// Multiplies two numbers
- Mul,
- /// Divides two numbers
- Div,
- /// Division remainder
- Rem,
- /// Bitwise AND
- BitAnd,
- /// Bitwise OR
- BitOr,
- /// Bitwise XOR
- BitXor,
+ /// Common instruction for add, sub, mul, div, rem, bit.and, bit.or, bit.xor, shl and shr.
+ BinaryNumericInstruction,
/// Bitwise NOT
BitNot,
/// Retrieves the RuntimeArgumentHandle.
@@ -125,10 +111,6 @@ namespace ICSharpCode.Decompiler.IL
LocAlloc,
/// Returns from the current method or lambda.
Return,
- /// Shift left
- Shl,
- /// Shift right
- Shr,
/// Load address of instance field
LdFlda,
/// Load static field address
@@ -722,157 +704,17 @@ namespace ICSharpCode.Decompiler.IL
}
}
- /// Adds two numbers.
- public sealed partial class Add : BinaryNumericInstruction
+ /// Common instruction for add, sub, mul, div, rem, bit.and, bit.or, bit.xor, shl and shr.
+ public sealed partial class BinaryNumericInstruction : BinaryInstruction
{
- public Add(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.Add, left, right, checkForOverflow, sign)
- {
- }
-
- public override void AcceptVisitor(ILVisitor visitor)
- {
- visitor.VisitAdd(this);
- }
- public override T AcceptVisitor(ILVisitor visitor)
- {
- return visitor.VisitAdd(this);
- }
- }
-
- /// Subtracts two numbers
- public sealed partial class Sub : BinaryNumericInstruction
- {
- public Sub(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.Sub, left, right, checkForOverflow, sign)
- {
- }
-
- public override void AcceptVisitor(ILVisitor visitor)
- {
- visitor.VisitSub(this);
- }
- public override T AcceptVisitor(ILVisitor visitor)
- {
- return visitor.VisitSub(this);
- }
- }
-
- /// Multiplies two numbers
- public sealed partial class Mul : BinaryNumericInstruction
- {
- public Mul(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.Mul, left, right, checkForOverflow, sign)
- {
- }
public override void AcceptVisitor(ILVisitor visitor)
{
- visitor.VisitMul(this);
+ visitor.VisitBinaryNumericInstruction(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
- return visitor.VisitMul(this);
- }
- }
-
- /// Divides two numbers
- public sealed partial class Div : BinaryNumericInstruction
- {
- public Div(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.Div, left, right, checkForOverflow, sign)
- {
- }
-
- protected override InstructionFlags ComputeFlags()
- {
- return base.ComputeFlags() | InstructionFlags.MayThrow;
- }
- public override InstructionFlags DirectFlags {
- get {
- return base.DirectFlags | InstructionFlags.MayThrow;
- }
- }
- public override void AcceptVisitor(ILVisitor visitor)
- {
- visitor.VisitDiv(this);
- }
- public override T AcceptVisitor(ILVisitor visitor)
- {
- return visitor.VisitDiv(this);
- }
- }
-
- /// Division remainder
- public sealed partial class Rem : BinaryNumericInstruction
- {
- public Rem(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.Rem, left, right, checkForOverflow, sign)
- {
- }
-
- protected override InstructionFlags ComputeFlags()
- {
- return base.ComputeFlags() | InstructionFlags.MayThrow;
- }
- public override InstructionFlags DirectFlags {
- get {
- return base.DirectFlags | InstructionFlags.MayThrow;
- }
- }
- public override void AcceptVisitor(ILVisitor visitor)
- {
- visitor.VisitRem(this);
- }
- public override T AcceptVisitor(ILVisitor visitor)
- {
- return visitor.VisitRem(this);
- }
- }
-
- /// Bitwise AND
- public sealed partial class BitAnd : BinaryNumericInstruction
- {
- public BitAnd(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.BitAnd, left, right, checkForOverflow, sign)
- {
- }
-
- public override void AcceptVisitor(ILVisitor visitor)
- {
- visitor.VisitBitAnd(this);
- }
- public override T AcceptVisitor(ILVisitor visitor)
- {
- return visitor.VisitBitAnd(this);
- }
- }
-
- /// Bitwise OR
- public sealed partial class BitOr : BinaryNumericInstruction
- {
- public BitOr(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.BitOr, left, right, checkForOverflow, sign)
- {
- }
-
- public override void AcceptVisitor(ILVisitor visitor)
- {
- visitor.VisitBitOr(this);
- }
- public override T AcceptVisitor(ILVisitor visitor)
- {
- return visitor.VisitBitOr(this);
- }
- }
-
- /// Bitwise XOR
- public sealed partial class BitXor : BinaryNumericInstruction
- {
- public BitXor(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.BitXor, left, right, checkForOverflow, sign)
- {
- }
-
- public override void AcceptVisitor(ILVisitor visitor)
- {
- visitor.VisitBitXor(this);
- }
- public override T AcceptVisitor(ILVisitor visitor)
- {
- return visitor.VisitBitXor(this);
+ return visitor.VisitBinaryNumericInstruction(this);
}
}
@@ -1985,40 +1827,6 @@ namespace ICSharpCode.Decompiler.IL
}
}
- /// Shift left
- public sealed partial class Shl : BinaryNumericInstruction
- {
- public Shl(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.Shl, left, right, checkForOverflow, sign)
- {
- }
-
- public override void AcceptVisitor(ILVisitor visitor)
- {
- visitor.VisitShl(this);
- }
- public override T AcceptVisitor(ILVisitor visitor)
- {
- return visitor.VisitShl(this);
- }
- }
-
- /// Shift right
- public sealed partial class Shr : BinaryNumericInstruction
- {
- public Shr(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.Shr, left, right, checkForOverflow, sign)
- {
- }
-
- public override void AcceptVisitor(ILVisitor visitor)
- {
- visitor.VisitShr(this);
- }
- public override T AcceptVisitor(ILVisitor visitor)
- {
- return visitor.VisitShr(this);
- }
- }
-
/// Load address of instance field
public sealed partial class LdFlda : ILInstruction, IInstructionWithFieldOperand
{
@@ -3110,35 +2918,7 @@ namespace ICSharpCode.Decompiler.IL
{
Default(inst);
}
- protected internal virtual void VisitAdd(Add inst)
- {
- Default(inst);
- }
- protected internal virtual void VisitSub(Sub inst)
- {
- Default(inst);
- }
- protected internal virtual void VisitMul(Mul inst)
- {
- Default(inst);
- }
- protected internal virtual void VisitDiv(Div inst)
- {
- Default(inst);
- }
- protected internal virtual void VisitRem(Rem inst)
- {
- Default(inst);
- }
- protected internal virtual void VisitBitAnd(BitAnd inst)
- {
- Default(inst);
- }
- protected internal virtual void VisitBitOr(BitOr inst)
- {
- Default(inst);
- }
- protected internal virtual void VisitBitXor(BitXor inst)
+ protected internal virtual void VisitBinaryNumericInstruction(BinaryNumericInstruction inst)
{
Default(inst);
}
@@ -3274,14 +3054,6 @@ namespace ICSharpCode.Decompiler.IL
{
Default(inst);
}
- protected internal virtual void VisitShl(Shl inst)
- {
- Default(inst);
- }
- protected internal virtual void VisitShr(Shr inst)
- {
- Default(inst);
- }
protected internal virtual void VisitLdFlda(LdFlda inst)
{
Default(inst);
@@ -3404,35 +3176,7 @@ namespace ICSharpCode.Decompiler.IL
{
return Default(inst);
}
- protected internal virtual T VisitAdd(Add inst)
- {
- return Default(inst);
- }
- protected internal virtual T VisitSub(Sub inst)
- {
- return Default(inst);
- }
- protected internal virtual T VisitMul(Mul inst)
- {
- return Default(inst);
- }
- protected internal virtual T VisitDiv(Div inst)
- {
- return Default(inst);
- }
- protected internal virtual T VisitRem(Rem inst)
- {
- return Default(inst);
- }
- protected internal virtual T VisitBitAnd(BitAnd inst)
- {
- return Default(inst);
- }
- protected internal virtual T VisitBitOr(BitOr inst)
- {
- return Default(inst);
- }
- protected internal virtual T VisitBitXor(BitXor inst)
+ protected internal virtual T VisitBinaryNumericInstruction(BinaryNumericInstruction inst)
{
return Default(inst);
}
@@ -3568,14 +3312,6 @@ namespace ICSharpCode.Decompiler.IL
{
return Default(inst);
}
- protected internal virtual T VisitShl(Shl inst)
- {
- return Default(inst);
- }
- protected internal virtual T VisitShr(Shr inst)
- {
- return Default(inst);
- }
protected internal virtual T VisitLdFlda(LdFlda inst)
{
return Default(inst);
@@ -3662,37 +3398,6 @@ namespace ICSharpCode.Decompiler.IL
}
}
- partial class BinaryNumericInstruction
- {
- 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);
- case OpCode.Sub:
- return new Sub(left, right, checkForOverflow, sign);
- case OpCode.Mul:
- return new Mul(left, right, checkForOverflow, sign);
- case OpCode.Div:
- return new Div(left, right, checkForOverflow, sign);
- case OpCode.Rem:
- return new Rem(left, right, checkForOverflow, sign);
- case OpCode.BitAnd:
- return new BitAnd(left, right, checkForOverflow, sign);
- case OpCode.BitOr:
- return new BitOr(left, right, checkForOverflow, sign);
- case OpCode.BitXor:
- return new BitXor(left, right, checkForOverflow, sign);
- case OpCode.Shl:
- return new Shl(left, right, checkForOverflow, sign);
- case OpCode.Shr:
- return new Shr(left, right, checkForOverflow, sign);
- default:
- throw new ArgumentException("opCode is not a binary numeric instruction");
- }
- }
- }
-
partial class BinaryComparisonInstruction
{
public static BinaryComparisonInstruction Create(OpCode opCode, ILInstruction left, ILInstruction right)
@@ -3714,14 +3419,7 @@ namespace ICSharpCode.Decompiler.IL
"Block",
"PinnedRegion",
"logic.not",
- "add",
- "sub",
- "mul",
- "div",
- "rem",
- "bit.and",
- "bit.or",
- "bit.xor",
+ "binary",
"bit.not",
"arglist",
"br",
@@ -3755,8 +3453,6 @@ namespace ICSharpCode.Decompiler.IL
"ldmembertoken",
"localloc",
"ret",
- "shl",
- "shr",
"ldflda",
"ldsflda",
"castclass",
@@ -3823,102 +3519,6 @@ namespace ICSharpCode.Decompiler.IL
argument = default(ILInstruction);
return false;
}
- public bool MatchAdd(out ILInstruction left, out ILInstruction right)
- {
- var inst = this as Add;
- if (inst != null) {
- left = inst.Left;
- right = inst.Right;
- return true;
- }
- left = default(ILInstruction);
- right = default(ILInstruction);
- return false;
- }
- public bool MatchSub(out ILInstruction left, out ILInstruction right)
- {
- var inst = this as Sub;
- if (inst != null) {
- left = inst.Left;
- right = inst.Right;
- return true;
- }
- left = default(ILInstruction);
- right = default(ILInstruction);
- return false;
- }
- public bool MatchMul(out ILInstruction left, out ILInstruction right)
- {
- var inst = this as Mul;
- if (inst != null) {
- left = inst.Left;
- right = inst.Right;
- return true;
- }
- left = default(ILInstruction);
- right = default(ILInstruction);
- return false;
- }
- public bool MatchDiv(out ILInstruction left, out ILInstruction right)
- {
- var inst = this as Div;
- if (inst != null) {
- left = inst.Left;
- right = inst.Right;
- return true;
- }
- left = default(ILInstruction);
- right = default(ILInstruction);
- return false;
- }
- public bool MatchRem(out ILInstruction left, out ILInstruction right)
- {
- var inst = this as Rem;
- if (inst != null) {
- left = inst.Left;
- right = inst.Right;
- return true;
- }
- left = default(ILInstruction);
- right = default(ILInstruction);
- return false;
- }
- public bool MatchBitAnd(out ILInstruction left, out ILInstruction right)
- {
- var inst = this as BitAnd;
- if (inst != null) {
- left = inst.Left;
- right = inst.Right;
- return true;
- }
- left = default(ILInstruction);
- right = default(ILInstruction);
- return false;
- }
- public bool MatchBitOr(out ILInstruction left, out ILInstruction right)
- {
- var inst = this as BitOr;
- if (inst != null) {
- left = inst.Left;
- right = inst.Right;
- return true;
- }
- left = default(ILInstruction);
- right = default(ILInstruction);
- return false;
- }
- public bool MatchBitXor(out ILInstruction left, out ILInstruction right)
- {
- var inst = this as BitXor;
- if (inst != null) {
- left = inst.Left;
- right = inst.Right;
- return true;
- }
- left = default(ILInstruction);
- right = default(ILInstruction);
- return false;
- }
public bool MatchBitNot(out ILInstruction argument)
{
var inst = this as BitNot;
@@ -4121,30 +3721,6 @@ namespace ICSharpCode.Decompiler.IL
argument = default(ILInstruction);
return false;
}
- public bool MatchShl(out ILInstruction left, out ILInstruction right)
- {
- var inst = this as Shl;
- if (inst != null) {
- left = inst.Left;
- right = inst.Right;
- return true;
- }
- left = default(ILInstruction);
- right = default(ILInstruction);
- return false;
- }
- public bool MatchShr(out ILInstruction left, out ILInstruction right)
- {
- var inst = this as Shr;
- if (inst != null) {
- left = inst.Left;
- right = inst.Right;
- return true;
- }
- left = default(ILInstruction);
- right = default(ILInstruction);
- return false;
- }
public bool MatchLdFlda(out ILInstruction target, out IField field)
{
var inst = this as LdFlda;
diff --git a/ICSharpCode.Decompiler/IL/Instructions.tt b/ICSharpCode.Decompiler/IL/Instructions.tt
index 8f745e076..96ed0bc88 100644
--- a/ICSharpCode.Decompiler/IL/Instructions.tt
+++ b/ICSharpCode.Decompiler/IL/Instructions.tt
@@ -58,14 +58,8 @@
})),
new OpCode("logic.not", "Unary operator that expects an input of type I4. Returns 1 (of type I4) if the input value is 0. Otherwise, returns 0 (of type I4).",
ResultType("I4"), Unary),
- new OpCode("add", "Adds two numbers.", BinaryNumeric),
- new OpCode("sub", "Subtracts two numbers", BinaryNumeric),
- new OpCode("mul", "Multiplies two numbers", BinaryNumeric),
- new OpCode("div", "Divides two numbers", BinaryNumeric, MayThrow),
- new OpCode("rem", "Division remainder", BinaryNumeric, MayThrow),
- new OpCode("bit.and", "Bitwise AND", BinaryNumeric),
- new OpCode("bit.or", "Bitwise OR", BinaryNumeric),
- new OpCode("bit.xor", "Bitwise XOR", BinaryNumeric),
+ 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),
new OpCode("bit.not", "Bitwise NOT", Unary),
new OpCode("arglist", "Retrieves the RuntimeArgumentHandle.", NoArguments, ResultType("O")),
new OpCode("br", "Unconditional branch. goto target;",
@@ -143,8 +137,6 @@
CustomClassName("LocAlloc"), Unary, ResultType("I"), MayThrow),
new OpCode("ret", "Returns from the current method or lambda.",
CustomClassName("Return"), CustomConstructor, CustomComputeFlags, MayBranch, UnconditionalBranch),
- new OpCode("shl", "Shift left", BinaryNumeric),
- new OpCode("shr", "Shift right", BinaryNumeric),
new OpCode("ldflda", "Load address of instance field",
CustomClassName("LdFlda"), CustomArguments("target"), MayThrowIfNotDelayed, HasFieldOperand, ResultType("Ref")),
@@ -289,21 +281,6 @@ namespace ICSharpCode.Decompiler.IL
<# } #>
}
- partial class BinaryNumericInstruction
- {
- 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);
-<# } #>
- default:
- throw new ArgumentException("opCode is not a binary numeric instruction");
- }
- }
- }
-
partial class BinaryComparisonInstruction
{
public static BinaryComparisonInstruction Create(OpCode opCode, ILInstruction left, ILInstruction right)
@@ -564,16 +541,6 @@ namespace ICSharpCode.Decompiler.IL
opCode.WriteArguments.Add("Right.WriteTo(output);");
opCode.WriteArguments.Add("output.Write(')');");
};
-
- // BinaryNumeric trait: the instruction is derived from BinaryNumericInstruction. Implies Binary; and implies MayThrow if the overflow mode is checked.
- static Action BinaryNumeric = opCode => {
- Binary(opCode);
- opCode.BaseClass = "BinaryNumericInstruction";
- opCode.ConstructorParameters.Add("bool checkForOverflow");
- opCode.BaseConstructorArguments.Add("checkForOverflow");
- opCode.ConstructorParameters.Add("Sign sign");
- opCode.BaseConstructorArguments.Add("sign");
- };
static Action CustomArguments(params string[] arguments)
{
diff --git a/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs
index 9be3a53c8..74c63f283 100644
--- a/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs
+++ b/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs
@@ -31,7 +31,21 @@ namespace ICSharpCode.Decompiler.IL
EvaluatesToNewValue
}
- public abstract partial class BinaryNumericInstruction : BinaryInstruction
+ public enum BinaryNumericOperator : byte
+ {
+ Add,
+ Sub,
+ Mul,
+ Div,
+ Rem,
+ BitAnd,
+ BitOr,
+ BitXor,
+ ShiftLeft,
+ ShiftRight
+ }
+
+ public partial class BinaryNumericInstruction : BinaryInstruction
{
///
/// Gets whether the instruction checks for overflow.
@@ -44,15 +58,21 @@ namespace ICSharpCode.Decompiler.IL
/// For instructions that produce the same result for either sign, returns Sign.None.
///
public readonly Sign Sign;
-
+
+ ///
+ /// The operator used by this binary operator instruction.
+ ///
+ public readonly BinaryNumericOperator Operator;
+
readonly StackType resultType;
- protected BinaryNumericInstruction(OpCode opCode, ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign)
- : base(opCode, left, right)
+ public BinaryNumericInstruction(BinaryNumericOperator op, ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign)
+ : base(OpCode.BinaryNumericInstruction, left, right)
{
this.CheckForOverflow = checkForOverflow;
this.Sign = sign;
- this.resultType = ComputeResultType(opCode, left.ResultType, right.ResultType);
+ this.Operator = op;
+ this.resultType = ComputeResultType(op, left.ResultType, right.ResultType);
Debug.Assert(resultType != StackType.Unknown);
//Debug.Assert(CompoundAssignmentType == CompoundAssignmentType.None || IsValidCompoundAssignmentTarget(Left));
}
@@ -71,23 +91,23 @@ namespace ICSharpCode.Decompiler.IL
}
}
- internal static StackType ComputeResultType(OpCode opCode, StackType left, StackType right)
+ internal static StackType ComputeResultType(BinaryNumericOperator op, StackType left, StackType right)
{
// Based on Table 2: Binary Numeric Operations
// also works for Table 5: Integer Operations
// and for Table 7: Overflow Arithmetic Operations
- if (left == right || opCode == OpCode.Shl || opCode == OpCode.Shr) {
+ if (left == right || op == BinaryNumericOperator.ShiftLeft || op == BinaryNumericOperator.ShiftRight) {
// Shift op codes use Table 6
return left;
}
if (left == StackType.Ref || right == StackType.Ref) {
if (left == StackType.Ref && right == StackType.Ref) {
// sub(&, &) = I
- Debug.Assert(opCode == OpCode.Sub);
+ Debug.Assert(op == BinaryNumericOperator.Sub);
return StackType.I;
} else {
// add/sub with I or I4 and &
- Debug.Assert(opCode == OpCode.Add || opCode == OpCode.Sub);
+ Debug.Assert(op == BinaryNumericOperator.Add || op == BinaryNumericOperator.Sub);
return StackType.Ref;
}
}
@@ -103,14 +123,51 @@ namespace ICSharpCode.Decompiler.IL
protected override InstructionFlags ComputeFlags()
{
var flags = base.ComputeFlags();
- if (CheckForOverflow)
+ if (CheckForOverflow || (Operator == BinaryNumericOperator.Div || Operator == BinaryNumericOperator.Rem))
flags |= InstructionFlags.MayThrow;
return flags;
}
+
+ public override InstructionFlags DirectFlags {
+ get {
+ if (Operator == BinaryNumericOperator.Div || Operator == BinaryNumericOperator.Rem)
+ return base.DirectFlags | InstructionFlags.MayThrow;
+ return base.DirectFlags;
+ }
+ }
+
+ string GetOperatorName(BinaryNumericOperator @operator)
+ {
+ switch (@operator) {
+ case BinaryNumericOperator.Add:
+ return "add";
+ case BinaryNumericOperator.Sub:
+ return "sub";
+ case BinaryNumericOperator.Mul:
+ return "mul";
+ case BinaryNumericOperator.Div:
+ return "div";
+ case BinaryNumericOperator.Rem:
+ return "rem";
+ case BinaryNumericOperator.BitAnd:
+ return "bit.and";
+ case BinaryNumericOperator.BitOr:
+ return "bit.or";
+ case BinaryNumericOperator.BitXor:
+ return "bit.xor";
+ case BinaryNumericOperator.ShiftLeft:
+ return "bit.shl";
+ case BinaryNumericOperator.ShiftRight:
+ return "bit.shr";
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
+ output.Write("." + GetOperatorName(Operator));
if (CheckForOverflow)
output.Write(".ovf");
if (Sign == Sign.Unsigned)
diff --git a/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs b/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs
index 128b525da..c728c5650 100644
--- a/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs
+++ b/ICSharpCode.Decompiler/IL/Instructions/PatternMatching.cs
@@ -202,6 +202,25 @@ namespace ICSharpCode.Decompiler.IL
return false;
}
+ public bool MatchBinaryNumericInstruction(BinaryNumericOperator @operator)
+ {
+ var op = this as BinaryNumericInstruction;
+ return op != null && op.Operator == @operator;
+ }
+
+ public bool MatchBinaryNumericInstruction(BinaryNumericOperator @operator, out ILInstruction left, out ILInstruction right)
+ {
+ var op = this as BinaryNumericInstruction;
+ if (op != null && op.Operator == @operator) {
+ left = op.Left;
+ right = op.Right;
+ return true;
+ }
+ left = null;
+ right = null;
+ return false;
+ }
+
///
/// If this instruction is a conversion of the specified kind, return its argument.
/// Otherwise, return the instruction itself.
diff --git a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs
index 09e76282c..70b69c3ed 100644
--- a/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs
+++ b/ICSharpCode.Decompiler/IL/Transforms/ILInlining.cs
@@ -267,7 +267,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}
return parent == next;
case OpCode.SwitchInstruction:
- return parent == next || (parent.OpCode == OpCode.Sub && parent.Parent == next);
+ return parent == next || (parent.MatchBinaryNumericInstruction(BinaryNumericOperator.Sub) && parent.Parent == next);
default:
return false;
}