Browse Source

Instead of OverflowMode, use bool checkForOverflow + Sign

pull/728/head
Daniel Grunwald 11 years ago
parent
commit
3d47e1028e
  1. 52
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  2. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  3. 106
      ICSharpCode.Decompiler/IL/ILReader.cs
  4. 8
      ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs
  5. 42
      ICSharpCode.Decompiler/IL/Instructions.cs
  6. 13
      ICSharpCode.Decompiler/IL/Instructions.tt
  7. 39
      ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs
  8. 21
      ICSharpCode.Decompiler/IL/Instructions/Conv.cs
  9. 125
      ICSharpCode.Decompiler/IL/NRTypeExtensions.cs
  10. 2
      ICSharpCode.Decompiler/IL/StackType.cs
  11. 4
      ILSpy/Properties/AssemblyInfo.template.cs

52
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -262,6 +262,58 @@ namespace ICSharpCode.Decompiler.CSharp @@ -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);
}
/// <summary>
/// Gets whether <paramref name="type"/> has the specified <paramref name="sign"/>.
/// If <paramref name="sign"/> is None, always returns true.
/// </summary>
bool IsCompatibleWithSign(IType type, Sign sign)
{
return sign == Sign.None || type.GetSign() == sign;
}
protected internal override ConvertedExpression VisitCall(Call inst)
{
return HandleCallInstruction(inst);

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -90,6 +90,7 @@ @@ -90,6 +90,7 @@
<Compile Include="IL\Instructions\SimpleInstruction.cs" />
<Compile Include="IL\Instructions\TryInstruction.cs" />
<Compile Include="IL\Instructions\UnaryInstruction.cs" />
<Compile Include="IL\NRTypeExtensions.cs" />
<Compile Include="IL\TransformingVisitor.cs" />
<Compile Include="TypesHierarchyHelpers.cs" />
<Compile Include="CecilExtensions.cs" />

106
ICSharpCode.Decompiler/IL/ILReader.cs

@ -188,11 +188,11 @@ namespace ICSharpCode.Decompiler.IL @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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);
}
}
}

8
ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs

@ -40,13 +40,5 @@ namespace ICSharpCode.Decompiler.IL @@ -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");
}
}
}

42
ICSharpCode.Decompiler/IL/Instructions.cs

@ -393,7 +393,7 @@ namespace ICSharpCode.Decompiler.IL @@ -393,7 +393,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Adds two numbers.</summary>
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 @@ -406,7 +406,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Subtracts two numbers</summary>
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 @@ -419,7 +419,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Multiplies two numbers</summary>
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 @@ -432,7 +432,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Divides two numbers</summary>
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 @@ -449,7 +449,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Division remainder</summary>
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 @@ -466,7 +466,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Bitwise AND</summary>
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 @@ -479,7 +479,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Bitwise OR</summary>
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 @@ -492,7 +492,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Bitwise XOR</summary>
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 @@ -1122,7 +1122,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Shift left</summary>
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 @@ -1135,7 +1135,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Shift right</summary>
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 @@ -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");
}

13
ICSharpCode.Decompiler/IL/Instructions.tt

@ -248,12 +248,12 @@ namespace ICSharpCode.Decompiler.IL @@ -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 @@ -477,9 +477,12 @@ namespace ICSharpCode.Decompiler.IL
static Action<OpCode> 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.

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

@ -24,29 +24,27 @@ using System.Text; @@ -24,29 +24,27 @@ using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
[Flags]
public enum OverflowMode : byte
{
/// <summary>Don't check for overflow, treat integers as signed.</summary>
None = 0,
/// <summary>Check for overflow, treat integers as signed.</summary>
Ovf = 1,
/// <summary>Don't check for overflow, treat integers as unsigned.</summary>
Un = 2,
/// <summary>Check for overflow, treat integers as unsigned.</summary>
Ovf_Un = 3
}
public abstract partial class BinaryNumericInstruction : BinaryInstruction
{
public readonly OverflowMode OverflowMode;
/// <summary>
/// Gets whether the instruction checks for overflow.
/// </summary>
public readonly bool CheckForOverflow;
/// <summary>
/// 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.
/// </summary>
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 @@ -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 @@ -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(", ");

21
ICSharpCode.Decompiler/IL/Instructions/Conv.cs

@ -23,12 +23,18 @@ namespace ICSharpCode.Decompiler.IL @@ -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)
/// <summary>
/// Gets the sign of the input type.
/// </summary>
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 @@ -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 @@ -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;
}

125
ICSharpCode.Decompiler/IL/NRTypeExtensions.cs

@ -0,0 +1,125 @@ @@ -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
}
}

2
ICSharpCode.Decompiler/IL/StackType.cs

@ -34,7 +34,7 @@ namespace ICSharpCode.Decompiler.IL @@ -34,7 +34,7 @@ namespace ICSharpCode.Decompiler.IL
I4,
/// <summary>64-bit integer</summary>
I8,
/// <summary>native-size integer</summary>
/// <summary>native-size integer, or unmanaged pointer</summary>
I,
/// <summary>Floating point number</summary>
F,

4
ILSpy/Properties/AssemblyInfo.template.cs

@ -31,8 +31,8 @@ using System.Runtime.InteropServices; @@ -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;

Loading…
Cancel
Save