diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
index c41db8776..0be2835dc 100644
--- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
+++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
@@ -216,7 +216,7 @@ namespace ICSharpCode.Decompiler.CSharp
return LogicNot(IsType((IsInst)inst.Left));
} else if (inst.Right.OpCode == OpCode.IsInst && inst.Left.OpCode == OpCode.LdNull) {
return LogicNot(IsType((IsInst)inst.Right));
- }
+ }
var left = ConvertArgument(inst.Left);
var right = ConvertArgument(inst.Right);
return new ConvertedExpression(
@@ -262,6 +262,58 @@ namespace ICSharpCode.Decompiler.CSharp
left.Type);
}
+ protected internal override ConvertedExpression VisitAdd(Add inst)
+ {
+ return HandleBinaryNumeric(inst, BinaryOperatorType.Add);
+ }
+
+ protected internal override ConvertedExpression VisitSub(Sub inst)
+ {
+ return HandleBinaryNumeric(inst, BinaryOperatorType.Subtract);
+ }
+
+ protected internal override ConvertedExpression VisitBitXor(BitXor inst)
+ {
+ return HandleBinaryNumeric(inst, BinaryOperatorType.ExclusiveOr);
+ }
+
+ protected internal override ConvertedExpression VisitShl(Shl inst)
+ {
+ return HandleBinaryNumeric(inst, BinaryOperatorType.ShiftLeft);
+ }
+
+ protected internal override ConvertedExpression VisitShr(Shr inst)
+ {
+ return HandleBinaryNumeric(inst, BinaryOperatorType.ShiftRight);
+ }
+
+ ConvertedExpression HandleBinaryNumeric(BinaryNumericInstruction inst, BinaryOperatorType op)
+ {
+ var left = ConvertArgument(inst.Left);
+ var right = ConvertArgument(inst.Right);
+ var rr = resolver.ResolveBinaryOperator(op, new ResolveResult(left.Type), new ResolveResult(right.Type));
+ if (!rr.IsError && rr.Type.GetStackType() == inst.ResultType
+ && IsCompatibleWithSign(left.Type, inst.Sign) && IsCompatibleWithSign(right.Type, inst.Sign))
+ {
+ return new ConvertedExpression(
+ new BinaryOperatorExpression(left.Expression, op, right.Expression),
+ rr.Type);
+ }
+ IType targetType = compilation.FindType(inst.ResultType.ToKnownTypeCode(inst.Sign));
+ return new ConvertedExpression(
+ new BinaryOperatorExpression(left.ConvertTo(targetType, this), op, right.ConvertTo(targetType, this)),
+ targetType);
+ }
+
+ ///
+ /// Gets whether has the specified .
+ /// If is None, always returns true.
+ ///
+ bool IsCompatibleWithSign(IType type, Sign sign)
+ {
+ return sign == Sign.None || type.GetSign() == sign;
+ }
+
protected internal override ConvertedExpression VisitCall(Call inst)
{
return HandleCallInstruction(inst);
diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
index 9df7331ec..ef6387b81 100644
--- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
+++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
@@ -90,6 +90,7 @@
+
diff --git a/ICSharpCode.Decompiler/IL/ILReader.cs b/ICSharpCode.Decompiler/IL/ILReader.cs
index 85a9da580..95953d0a8 100644
--- a/ICSharpCode.Decompiler/IL/ILReader.cs
+++ b/ICSharpCode.Decompiler/IL/ILReader.cs
@@ -188,11 +188,11 @@ namespace ICSharpCode.Decompiler.IL
switch (stack.PeekOrDefault()) {
case StackType.I4:
case StackType.I:
- return new Sub(new LdcI4(0), Pop(), OverflowMode.None);
+ return new Sub(new LdcI4(0), Pop(), checkForOverflow: false, sign: Sign.None);
case StackType.I8:
- return new Sub(new LdcI8(0), Pop(), OverflowMode.None);
+ return new Sub(new LdcI8(0), Pop(), checkForOverflow: false, sign: Sign.None);
case StackType.F:
- return new Sub(new LdcF(0), Pop(), OverflowMode.None);
+ return new Sub(new LdcF(0), Pop(), checkForOverflow: false, sign: Sign.None);
default:
Warn("Unsupported input type for neg: ");
goto case StackType.I4;
@@ -216,9 +216,9 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Add:
return BinaryNumeric(OpCode.Add);
case ILOpCode.Add_Ovf:
- return BinaryNumeric(OpCode.Add, OverflowMode.Ovf);
+ return BinaryNumeric(OpCode.Add, true, Sign.Signed);
case ILOpCode.Add_Ovf_Un:
- return BinaryNumeric(OpCode.Add, OverflowMode.Ovf_Un);
+ return BinaryNumeric(OpCode.Add, true, Sign.Unsigned);
case ILOpCode.And:
return BinaryNumeric(OpCode.BitAnd);
case ILOpCode.Arglist:
@@ -296,77 +296,77 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Ckfinite:
return new Ckfinite();
case ILOpCode.Conv_I1:
- return new Conv(Pop(), PrimitiveType.I1, OverflowMode.None);
+ return new Conv(Pop(), PrimitiveType.I1, false, Sign.None);
case ILOpCode.Conv_I2:
- return new Conv(Pop(), PrimitiveType.I2, OverflowMode.None);
+ return new Conv(Pop(), PrimitiveType.I2, false, Sign.None);
case ILOpCode.Conv_I4:
- return new Conv(Pop(), PrimitiveType.I4, OverflowMode.None);
+ return new Conv(Pop(), PrimitiveType.I4, false, Sign.None);
case ILOpCode.Conv_I8:
- return new Conv(Pop(), PrimitiveType.I8, OverflowMode.None);
+ return new Conv(Pop(), PrimitiveType.I8, false, Sign.None);
case ILOpCode.Conv_R4:
- return new Conv(Pop(), PrimitiveType.R4, OverflowMode.None);
+ return new Conv(Pop(), PrimitiveType.R4, false, Sign.Signed);
case ILOpCode.Conv_R8:
- return new Conv(Pop(), PrimitiveType.R8, OverflowMode.None);
+ return new Conv(Pop(), PrimitiveType.R8, false, Sign.Signed);
case ILOpCode.Conv_U1:
- return new Conv(Pop(), PrimitiveType.U1, OverflowMode.None);
+ return new Conv(Pop(), PrimitiveType.U1, false, Sign.None);
case ILOpCode.Conv_U2:
- return new Conv(Pop(), PrimitiveType.U2, OverflowMode.None);
+ return new Conv(Pop(), PrimitiveType.U2, false, Sign.None);
case ILOpCode.Conv_U4:
- return new Conv(Pop(), PrimitiveType.U4, OverflowMode.None);
+ return new Conv(Pop(), PrimitiveType.U4, false, Sign.None);
case ILOpCode.Conv_U8:
- return new Conv(Pop(), PrimitiveType.U8, OverflowMode.None);
+ return new Conv(Pop(), PrimitiveType.U8, false, Sign.None);
case ILOpCode.Conv_I:
- return new Conv(Pop(), PrimitiveType.I, OverflowMode.None);
+ return new Conv(Pop(), PrimitiveType.I, false, Sign.None);
case ILOpCode.Conv_U:
- return new Conv(Pop(), PrimitiveType.U, OverflowMode.None);
+ return new Conv(Pop(), PrimitiveType.U, false, Sign.None);
case ILOpCode.Conv_R_Un:
- return new Conv(Pop(), PrimitiveType.R8, OverflowMode.Un);
+ return new Conv(Pop(), PrimitiveType.R8, false, Sign.Unsigned);
case ILOpCode.Conv_Ovf_I1:
- return new Conv(Pop(), PrimitiveType.I1, OverflowMode.Ovf);
+ return new Conv(Pop(), PrimitiveType.I1, true, Sign.Signed);
case ILOpCode.Conv_Ovf_I2:
- return new Conv(Pop(), PrimitiveType.I2, OverflowMode.Ovf);
+ return new Conv(Pop(), PrimitiveType.I2, true, Sign.Signed);
case ILOpCode.Conv_Ovf_I4:
- return new Conv(Pop(), PrimitiveType.I4, OverflowMode.Ovf);
+ return new Conv(Pop(), PrimitiveType.I4, true, Sign.Signed);
case ILOpCode.Conv_Ovf_I8:
- return new Conv(Pop(), PrimitiveType.I8, OverflowMode.Ovf);
+ return new Conv(Pop(), PrimitiveType.I8, true, Sign.Signed);
case ILOpCode.Conv_Ovf_U1:
- return new Conv(Pop(), PrimitiveType.U1, OverflowMode.Ovf);
+ return new Conv(Pop(), PrimitiveType.U1, true, Sign.Signed);
case ILOpCode.Conv_Ovf_U2:
- return new Conv(Pop(), PrimitiveType.U2, OverflowMode.Ovf);
+ return new Conv(Pop(), PrimitiveType.U2, true, Sign.Signed);
case ILOpCode.Conv_Ovf_U4:
- return new Conv(Pop(), PrimitiveType.U4, OverflowMode.Ovf);
+ return new Conv(Pop(), PrimitiveType.U4, true, Sign.Signed);
case ILOpCode.Conv_Ovf_U8:
- return new Conv(Pop(), PrimitiveType.U8, OverflowMode.Ovf);
+ return new Conv(Pop(), PrimitiveType.U8, true, Sign.Signed);
case ILOpCode.Conv_Ovf_I:
- return new Conv(Pop(), PrimitiveType.I, OverflowMode.Ovf);
+ return new Conv(Pop(), PrimitiveType.I, true, Sign.Signed);
case ILOpCode.Conv_Ovf_U:
- return new Conv(Pop(), PrimitiveType.U, OverflowMode.Ovf);
+ return new Conv(Pop(), PrimitiveType.U, true, Sign.Signed);
case ILOpCode.Conv_Ovf_I1_Un:
- return new Conv(Pop(), PrimitiveType.I1, OverflowMode.Ovf_Un);
+ return new Conv(Pop(), PrimitiveType.I1, true, Sign.Unsigned);
case ILOpCode.Conv_Ovf_I2_Un:
- return new Conv(Pop(), PrimitiveType.I2, OverflowMode.Ovf_Un);
+ return new Conv(Pop(), PrimitiveType.I2, true, Sign.Unsigned);
case ILOpCode.Conv_Ovf_I4_Un:
- return new Conv(Pop(), PrimitiveType.I4, OverflowMode.Ovf_Un);
+ return new Conv(Pop(), PrimitiveType.I4, true, Sign.Unsigned);
case ILOpCode.Conv_Ovf_I8_Un:
- return new Conv(Pop(), PrimitiveType.I8, OverflowMode.Ovf_Un);
+ return new Conv(Pop(), PrimitiveType.I8, true, Sign.Unsigned);
case ILOpCode.Conv_Ovf_U1_Un:
- return new Conv(Pop(), PrimitiveType.U1, OverflowMode.Ovf_Un);
+ return new Conv(Pop(), PrimitiveType.U1, true, Sign.Unsigned);
case ILOpCode.Conv_Ovf_U2_Un:
- return new Conv(Pop(), PrimitiveType.U2, OverflowMode.Ovf_Un);
+ return new Conv(Pop(), PrimitiveType.U2, true, Sign.Unsigned);
case ILOpCode.Conv_Ovf_U4_Un:
- return new Conv(Pop(), PrimitiveType.U4, OverflowMode.Ovf_Un);
+ return new Conv(Pop(), PrimitiveType.U4, true, Sign.Unsigned);
case ILOpCode.Conv_Ovf_U8_Un:
- return new Conv(Pop(), PrimitiveType.U8, OverflowMode.Ovf_Un);
+ return new Conv(Pop(), PrimitiveType.U8, true, Sign.Unsigned);
case ILOpCode.Conv_Ovf_I_Un:
- return new Conv(Pop(), PrimitiveType.I, OverflowMode.Ovf_Un);
+ return new Conv(Pop(), PrimitiveType.I, true, Sign.Unsigned);
case ILOpCode.Conv_Ovf_U_Un:
- return new Conv(Pop(), PrimitiveType.U, OverflowMode.Ovf_Un);
+ return new Conv(Pop(), PrimitiveType.U, true, Sign.Unsigned);
case ILOpCode.Cpblk:
throw new NotImplementedException();
case ILOpCode.Div:
- return BinaryNumeric(OpCode.Div, OverflowMode.None);
+ return BinaryNumeric(OpCode.Div, false, Sign.Signed);
case ILOpCode.Div_Un:
- return BinaryNumeric(OpCode.Div, OverflowMode.Un);
+ return BinaryNumeric(OpCode.Div, false, Sign.Unsigned);
case ILOpCode.Dup:
return new Peek(stack.Count > 0 ? stack.Peek() : StackType.Unknown);
case ILOpCode.Endfilter:
@@ -458,11 +458,11 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Localloc:
return new LocAlloc(Pop());
case ILOpCode.Mul:
- return BinaryNumeric(OpCode.Mul, OverflowMode.None);
+ return BinaryNumeric(OpCode.Mul, false, Sign.None);
case ILOpCode.Mul_Ovf:
- return BinaryNumeric(OpCode.Mul, OverflowMode.Ovf);
+ return BinaryNumeric(OpCode.Mul, true, Sign.Signed);
case ILOpCode.Mul_Ovf_Un:
- return BinaryNumeric(OpCode.Mul, OverflowMode.Ovf_Un);
+ return BinaryNumeric(OpCode.Mul, true, Sign.Unsigned);
case ILOpCode.Neg:
return Neg();
case ILOpCode.Newobj:
@@ -476,17 +476,17 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Pop:
return new Void(Pop());
case ILOpCode.Rem:
- return BinaryNumeric(OpCode.Rem, OverflowMode.None);
+ return BinaryNumeric(OpCode.Rem, false, Sign.Signed);
case ILOpCode.Rem_Un:
- return BinaryNumeric(OpCode.Rem, OverflowMode.Un);
+ return BinaryNumeric(OpCode.Rem, false, Sign.Unsigned);
case ILOpCode.Ret:
return Return();
case ILOpCode.Shl:
- return BinaryNumeric(OpCode.Shl, OverflowMode.None);
+ return BinaryNumeric(OpCode.Shl, false, Sign.None);
case ILOpCode.Shr:
- return BinaryNumeric(OpCode.Shr, OverflowMode.None);
+ return BinaryNumeric(OpCode.Shr, false, Sign.Signed);
case ILOpCode.Shr_Un:
- return BinaryNumeric(OpCode.Shr, OverflowMode.Un);
+ return BinaryNumeric(OpCode.Shr, false, Sign.Unsigned);
case ILOpCode.Starg:
return Starg(reader.ReadUInt16());
case ILOpCode.Starg_S:
@@ -517,11 +517,11 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Stloc_3:
return Stloc(ilOpCode - ILOpCode.Stloc_0);
case ILOpCode.Sub:
- return BinaryNumeric(OpCode.Sub);
+ return BinaryNumeric(OpCode.Sub, false, Sign.None);
case ILOpCode.Sub_Ovf:
- return BinaryNumeric(OpCode.Sub, OverflowMode.Ovf);
+ return BinaryNumeric(OpCode.Sub, true, Sign.Signed);
case ILOpCode.Sub_Ovf_Un:
- return BinaryNumeric(OpCode.Sub, OverflowMode.Ovf_Un);
+ return BinaryNumeric(OpCode.Sub, true, Sign.Unsigned);
case ILOpCode.Switch:
throw new NotImplementedException();
case ILOpCode.Xor:
@@ -793,11 +793,11 @@ namespace ICSharpCode.Decompiler.IL
}
}
- ILInstruction BinaryNumeric(OpCode opCode, OverflowMode overflowMode = OverflowMode.None)
+ ILInstruction BinaryNumeric(OpCode opCode, bool checkForOverflow = false, Sign sign = Sign.None)
{
var right = Pop();
var left = Pop();
- return BinaryNumericInstruction.Create(opCode, left, right, overflowMode);
+ return BinaryNumericInstruction.Create(opCode, left, right, checkForOverflow, sign);
}
}
}
diff --git a/ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs b/ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs
index e055f8d52..e7d673084 100644
--- a/ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs
+++ b/ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs
@@ -40,13 +40,5 @@ namespace ICSharpCode.Decompiler.IL
{
output.Write(primitiveType.ToString().ToLowerInvariant());
}
-
- public static void WriteSuffix(this ITextOutput output, OverflowMode mode)
- {
- if ((mode & OverflowMode.Ovf) != 0)
- output.Write(".ovf");
- if ((mode & OverflowMode.Un) != 0)
- output.Write(".un");
- }
}
}
diff --git a/ICSharpCode.Decompiler/IL/Instructions.cs b/ICSharpCode.Decompiler/IL/Instructions.cs
index 9e8e11b31..2138a17c3 100644
--- a/ICSharpCode.Decompiler/IL/Instructions.cs
+++ b/ICSharpCode.Decompiler/IL/Instructions.cs
@@ -393,7 +393,7 @@ namespace ICSharpCode.Decompiler.IL
/// Adds two numbers.
public sealed partial class Add : BinaryNumericInstruction
{
- public Add(ILInstruction left, ILInstruction right, OverflowMode overflowMode) : base(OpCode.Add, left, right, overflowMode)
+ public Add(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.Add, left, right, checkForOverflow, sign)
{
}
@@ -406,7 +406,7 @@ namespace ICSharpCode.Decompiler.IL
/// Subtracts two numbers
public sealed partial class Sub : BinaryNumericInstruction
{
- public Sub(ILInstruction left, ILInstruction right, OverflowMode overflowMode) : base(OpCode.Sub, left, right, overflowMode)
+ public Sub(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.Sub, left, right, checkForOverflow, sign)
{
}
@@ -419,7 +419,7 @@ namespace ICSharpCode.Decompiler.IL
/// Multiplies two numbers
public sealed partial class Mul : BinaryNumericInstruction
{
- public Mul(ILInstruction left, ILInstruction right, OverflowMode overflowMode) : base(OpCode.Mul, left, right, overflowMode)
+ public Mul(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.Mul, left, right, checkForOverflow, sign)
{
}
@@ -432,7 +432,7 @@ namespace ICSharpCode.Decompiler.IL
/// Divides two numbers
public sealed partial class Div : BinaryNumericInstruction
{
- public Div(ILInstruction left, ILInstruction right, OverflowMode overflowMode) : base(OpCode.Div, left, right, overflowMode)
+ public Div(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.Div, left, right, checkForOverflow, sign)
{
}
@@ -449,7 +449,7 @@ namespace ICSharpCode.Decompiler.IL
/// Division remainder
public sealed partial class Rem : BinaryNumericInstruction
{
- public Rem(ILInstruction left, ILInstruction right, OverflowMode overflowMode) : base(OpCode.Rem, left, right, overflowMode)
+ public Rem(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.Rem, left, right, checkForOverflow, sign)
{
}
@@ -466,7 +466,7 @@ namespace ICSharpCode.Decompiler.IL
/// Bitwise AND
public sealed partial class BitAnd : BinaryNumericInstruction
{
- public BitAnd(ILInstruction left, ILInstruction right, OverflowMode overflowMode) : base(OpCode.BitAnd, left, right, overflowMode)
+ public BitAnd(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.BitAnd, left, right, checkForOverflow, sign)
{
}
@@ -479,7 +479,7 @@ namespace ICSharpCode.Decompiler.IL
/// Bitwise OR
public sealed partial class BitOr : BinaryNumericInstruction
{
- public BitOr(ILInstruction left, ILInstruction right, OverflowMode overflowMode) : base(OpCode.BitOr, left, right, overflowMode)
+ public BitOr(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.BitOr, left, right, checkForOverflow, sign)
{
}
@@ -492,7 +492,7 @@ namespace ICSharpCode.Decompiler.IL
/// Bitwise XOR
public sealed partial class BitXor : BinaryNumericInstruction
{
- public BitXor(ILInstruction left, ILInstruction right, OverflowMode overflowMode) : base(OpCode.BitXor, left, right, overflowMode)
+ public BitXor(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.BitXor, left, right, checkForOverflow, sign)
{
}
@@ -1122,7 +1122,7 @@ namespace ICSharpCode.Decompiler.IL
/// Shift left
public sealed partial class Shl : BinaryNumericInstruction
{
- public Shl(ILInstruction left, ILInstruction right, OverflowMode overflowMode) : base(OpCode.Shl, left, right, overflowMode)
+ public Shl(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.Shl, left, right, checkForOverflow, sign)
{
}
@@ -1135,7 +1135,7 @@ namespace ICSharpCode.Decompiler.IL
/// Shift right
public sealed partial class Shr : BinaryNumericInstruction
{
- public Shr(ILInstruction left, ILInstruction right, OverflowMode overflowMode) : base(OpCode.Shr, left, right, overflowMode)
+ public Shr(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign) : base(OpCode.Shr, left, right, checkForOverflow, sign)
{
}
@@ -2272,29 +2272,29 @@ namespace ICSharpCode.Decompiler.IL
partial class BinaryNumericInstruction
{
- public static BinaryNumericInstruction Create(OpCode opCode, ILInstruction left, ILInstruction right, OverflowMode overflowMode)
+ public static BinaryNumericInstruction Create(OpCode opCode, ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign)
{
switch (opCode) {
case OpCode.Add:
- return new Add(left, right, overflowMode);
+ return new Add(left, right, checkForOverflow, sign);
case OpCode.Sub:
- return new Sub(left, right, overflowMode);
+ return new Sub(left, right, checkForOverflow, sign);
case OpCode.Mul:
- return new Mul(left, right, overflowMode);
+ return new Mul(left, right, checkForOverflow, sign);
case OpCode.Div:
- return new Div(left, right, overflowMode);
+ return new Div(left, right, checkForOverflow, sign);
case OpCode.Rem:
- return new Rem(left, right, overflowMode);
+ return new Rem(left, right, checkForOverflow, sign);
case OpCode.BitAnd:
- return new BitAnd(left, right, overflowMode);
+ return new BitAnd(left, right, checkForOverflow, sign);
case OpCode.BitOr:
- return new BitOr(left, right, overflowMode);
+ return new BitOr(left, right, checkForOverflow, sign);
case OpCode.BitXor:
- return new BitXor(left, right, overflowMode);
+ return new BitXor(left, right, checkForOverflow, sign);
case OpCode.Shl:
- return new Shl(left, right, overflowMode);
+ return new Shl(left, right, checkForOverflow, sign);
case OpCode.Shr:
- return new Shr(left, right, overflowMode);
+ return new Shr(left, right, checkForOverflow, sign);
default:
throw new ArgumentException("opCode is not a binary numeric instruction");
}
diff --git a/ICSharpCode.Decompiler/IL/Instructions.tt b/ICSharpCode.Decompiler/IL/Instructions.tt
index 08aff0c94..ecf1e05a6 100644
--- a/ICSharpCode.Decompiler/IL/Instructions.tt
+++ b/ICSharpCode.Decompiler/IL/Instructions.tt
@@ -248,12 +248,12 @@ namespace ICSharpCode.Decompiler.IL
partial class BinaryNumericInstruction
{
- public static BinaryNumericInstruction Create(OpCode opCode, ILInstruction left, ILInstruction right, OverflowMode overflowMode)
+ 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, overflowMode);
+ return new <#=opCode.Name#>(left, right, checkForOverflow, sign);
<# } #>
default:
throw new ArgumentException("opCode is not a binary numeric instruction");
@@ -477,9 +477,12 @@ namespace ICSharpCode.Decompiler.IL
static Action BinaryNumeric = opCode => {
Binary(opCode);
opCode.BaseClass = "BinaryNumericInstruction";
- opCode.ConstructorParameters.Add("OverflowMode overflowMode");
- opCode.BaseConstructorArguments.Add("overflowMode");
- opCode.WriteOpCodeSuffix.Add("output.WriteSuffix(overflowMode);");
+ opCode.ConstructorParameters.Add("bool checkForOverflow");
+ opCode.BaseConstructorArguments.Add("checkForOverflow");
+ opCode.WriteOpCodeSuffix.Add("if (checkForOverflow) output.Write(\".ovf\");");
+ opCode.ConstructorParameters.Add("Sign sign");
+ opCode.BaseConstructorArguments.Add("sign");
+ opCode.WriteOpCodeSuffix.Add("if (sign == Sign.Unsigned) output.Write(\".un\");");
};
// BinaryNumeric trait: the instruction is derived from BinaryComparisonInstruction. Implies Binary and I4Result.
diff --git a/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs b/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs
index 62eff22ec..2a656f65e 100644
--- a/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs
+++ b/ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs
@@ -24,29 +24,27 @@ using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
- [Flags]
- public enum OverflowMode : byte
- {
- /// Don't check for overflow, treat integers as signed.
- None = 0,
- /// Check for overflow, treat integers as signed.
- Ovf = 1,
- /// Don't check for overflow, treat integers as unsigned.
- Un = 2,
- /// Check for overflow, treat integers as unsigned.
- Ovf_Un = 3
- }
-
public abstract partial class BinaryNumericInstruction : BinaryInstruction
{
- public readonly OverflowMode OverflowMode;
+ ///
+ /// Gets whether the instruction checks for overflow.
+ ///
+ public readonly bool CheckForOverflow;
+
+ ///
+ /// For integer operations that depend on the sign, specifies whether the operation
+ /// is signed or unsigned.
+ /// For instructions that produce the same result for either sign, returns Sign.None.
+ ///
+ public readonly Sign Sign;
readonly StackType resultType;
- protected BinaryNumericInstruction(OpCode opCode, ILInstruction left, ILInstruction right, OverflowMode overflowMode)
+ protected BinaryNumericInstruction(OpCode opCode, ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign)
: base(opCode, left, right)
{
- this.OverflowMode = overflowMode;
+ this.CheckForOverflow = checkForOverflow;
+ this.Sign = sign;
this.resultType = ComputeResultType(opCode, left.ResultType, right.ResultType);
}
@@ -83,7 +81,7 @@ namespace ICSharpCode.Decompiler.IL
protected override InstructionFlags ComputeFlags()
{
var flags = base.ComputeFlags();
- if ((OverflowMode & OverflowMode.Ovf) != 0)
+ if (CheckForOverflow)
flags |= InstructionFlags.MayThrow;
return flags;
}
@@ -91,7 +89,12 @@ namespace ICSharpCode.Decompiler.IL
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
- output.WriteSuffix(OverflowMode);
+ if (CheckForOverflow)
+ output.Write(".ovf");
+ if (Sign == Sign.Unsigned)
+ output.Write(".unsigned");
+ else if (Sign == Sign.Signed)
+ output.Write(".signed");
output.Write('(');
Left.WriteTo(output);
output.Write(", ");
diff --git a/ICSharpCode.Decompiler/IL/Instructions/Conv.cs b/ICSharpCode.Decompiler/IL/Instructions/Conv.cs
index 4b8dea48f..106e8811b 100644
--- a/ICSharpCode.Decompiler/IL/Instructions/Conv.cs
+++ b/ICSharpCode.Decompiler/IL/Instructions/Conv.cs
@@ -23,12 +23,18 @@ namespace ICSharpCode.Decompiler.IL
partial class Conv : UnaryInstruction
{
public readonly PrimitiveType TargetType;
- public readonly OverflowMode ConvMode;
+ public readonly bool CheckForOverflow;
- public Conv(ILInstruction argument, PrimitiveType targetType, OverflowMode convMode) : base(OpCode.Conv, argument)
+ ///
+ /// Gets the sign of the input type.
+ ///
+ public readonly Sign Sign;
+
+ public Conv(ILInstruction argument, PrimitiveType targetType, bool checkForOverflow, Sign sign) : base(OpCode.Conv, argument)
{
this.TargetType = targetType;
- this.ConvMode = convMode;
+ this.CheckForOverflow = checkForOverflow;
+ this.Sign = sign;
}
public override StackType ResultType {
@@ -38,7 +44,12 @@ namespace ICSharpCode.Decompiler.IL
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
- output.WriteSuffix(ConvMode);
+ if (CheckForOverflow)
+ output.Write(".ovf");
+ if (Sign == Sign.Unsigned)
+ output.Write(".unsigned");
+ else if (Sign == Sign.Signed)
+ output.Write(".signed");
output.Write(' ');
output.Write(Argument.ResultType);
output.Write("->");
@@ -51,7 +62,7 @@ namespace ICSharpCode.Decompiler.IL
protected override InstructionFlags ComputeFlags()
{
var flags = base.ComputeFlags();
- if ((ConvMode & OverflowMode.Ovf) != 0)
+ if (CheckForOverflow)
flags |= InstructionFlags.MayThrow;
return flags;
}
diff --git a/ICSharpCode.Decompiler/IL/NRTypeExtensions.cs b/ICSharpCode.Decompiler/IL/NRTypeExtensions.cs
new file mode 100644
index 000000000..e4a321f04
--- /dev/null
+++ b/ICSharpCode.Decompiler/IL/NRTypeExtensions.cs
@@ -0,0 +1,125 @@
+// Copyright (c) 2014 Daniel Grunwald
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using ICSharpCode.NRefactory.TypeSystem;
+
+namespace ICSharpCode.Decompiler.IL
+{
+ public static class NRTypeExtensions
+ {
+ public static StackType GetStackType(this IType type)
+ {
+ switch (type.Kind)
+ {
+ case TypeKind.Unknown:
+ return StackType.Unknown;
+ case TypeKind.ByReference:
+ return StackType.Ref;
+ case TypeKind.Pointer:
+ return StackType.I;
+ }
+ ITypeDefinition typeDef = type.GetDefinition();
+ if (typeDef == null)
+ return StackType.O;
+ if (typeDef.Kind == TypeKind.Enum) {
+ typeDef = typeDef.EnumUnderlyingType.GetDefinition();
+ if (typeDef == null)
+ return StackType.O;
+ }
+ switch (typeDef.KnownTypeCode) {
+ case KnownTypeCode.Boolean:
+ case KnownTypeCode.Char:
+ case KnownTypeCode.SByte:
+ case KnownTypeCode.Byte:
+ case KnownTypeCode.Int16:
+ case KnownTypeCode.UInt16:
+ case KnownTypeCode.Int32:
+ case KnownTypeCode.UInt32:
+ return StackType.I4;
+ case KnownTypeCode.Int64:
+ case KnownTypeCode.UInt64:
+ return StackType.I8;
+ case KnownTypeCode.Single:
+ case KnownTypeCode.Double:
+ return StackType.F;
+ case KnownTypeCode.Void:
+ return StackType.Void;
+ case KnownTypeCode.IntPtr:
+ case KnownTypeCode.UIntPtr:
+ return StackType.I;
+ default:
+ return StackType.O;
+ }
+ }
+
+ public static Sign GetSign(this IType type)
+ {
+ var typeDef = type.GetDefinition();
+ if (typeDef == null)
+ return Sign.None;
+ switch (typeDef.KnownTypeCode) {
+ case KnownTypeCode.SByte:
+ case KnownTypeCode.Int16:
+ case KnownTypeCode.Int32:
+ case KnownTypeCode.Int64:
+ case KnownTypeCode.IntPtr:
+ case KnownTypeCode.Single:
+ case KnownTypeCode.Double:
+ case KnownTypeCode.Decimal:
+ return Sign.Signed;
+ case KnownTypeCode.UIntPtr:
+ case KnownTypeCode.Char:
+ case KnownTypeCode.Byte:
+ case KnownTypeCode.UInt16:
+ case KnownTypeCode.UInt32:
+ case KnownTypeCode.UInt64:
+ return Sign.Unsigned;
+ default:
+ return Sign.None;
+ }
+ }
+
+ public static KnownTypeCode ToKnownTypeCode(this StackType stackType, Sign sign = Sign.None)
+ {
+ switch (stackType) {
+ case StackType.I4:
+ return sign == Sign.Unsigned ? KnownTypeCode.UInt32 : KnownTypeCode.Int32;
+ case StackType.I8:
+ return sign == Sign.Unsigned ? KnownTypeCode.UInt64 : KnownTypeCode.Int64;
+ case StackType.I:
+ return sign == Sign.Unsigned ? KnownTypeCode.UIntPtr : KnownTypeCode.IntPtr;
+ case StackType.F:
+ return KnownTypeCode.Double;
+ case StackType.O:
+ return KnownTypeCode.Object;
+ case StackType.Void:
+ return KnownTypeCode.Void;
+ default:
+ return KnownTypeCode.None;
+ }
+ }
+ }
+
+ public enum Sign
+ {
+ None,
+ Signed,
+ Unsigned
+ }
+}
diff --git a/ICSharpCode.Decompiler/IL/StackType.cs b/ICSharpCode.Decompiler/IL/StackType.cs
index 89c353365..e5cac8101 100644
--- a/ICSharpCode.Decompiler/IL/StackType.cs
+++ b/ICSharpCode.Decompiler/IL/StackType.cs
@@ -34,7 +34,7 @@ namespace ICSharpCode.Decompiler.IL
I4,
/// 64-bit integer
I8,
- /// native-size integer
+ /// native-size integer, or unmanaged pointer
I,
/// Floating point number
F,
diff --git a/ILSpy/Properties/AssemblyInfo.template.cs b/ILSpy/Properties/AssemblyInfo.template.cs
index 3a392ca5a..c05ed222d 100644
--- a/ILSpy/Properties/AssemblyInfo.template.cs
+++ b/ILSpy/Properties/AssemblyInfo.template.cs
@@ -31,8 +31,8 @@ using System.Runtime.InteropServices;
internal static class RevisionClass
{
- public const string Major = "2";
- public const string Minor = "1";
+ public const string Major = "3";
+ public const string Minor = "0";
public const string Build = "0";
public const string Revision = "$INSERTREVISION$";
public const string VersionName = null;