Browse Source

Improved decompilation correctness for operators on nullable values

pull/205/head
Pent Ploompuu 14 years ago
parent
commit
fec24cf171
  1. 7
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  2. 31
      ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs
  3. 5
      ICSharpCode.Decompiler/ILAst/ILCodes.cs
  4. 89
      ICSharpCode.Decompiler/ILAst/NullableOperators.cs
  5. 60
      ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs
  6. 10
      ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs
  7. 3
      ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs

7
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -396,6 +396,7 @@ namespace ICSharpCode.Decompiler.Ast
#endregion #endregion
#region Comparison #region Comparison
case ILCode.Ceq: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, arg2); case ILCode.Ceq: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, arg2);
case ILCode.Cne: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, arg2);
case ILCode.Cgt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2); case ILCode.Cgt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2);
case ILCode.Cgt_Un: { case ILCode.Cgt_Un: {
// can also mean Inequality, when used with object references // can also mean Inequality, when used with object references
@ -405,8 +406,12 @@ namespace ICSharpCode.Decompiler.Ast
else else
return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2); return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2);
} }
case ILCode.Clt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2); case ILCode.Cge:
case ILCode.Cge_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2);
case ILCode.Clt:
case ILCode.Clt_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2); case ILCode.Clt_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2);
case ILCode.Cle:
case ILCode.Cle_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2);
#endregion #endregion
#region Logical #region Logical
case ILCode.LogicNot: return new Ast.UnaryOperatorExpression(UnaryOperatorType.Not, arg1); case ILCode.LogicNot: return new Ast.UnaryOperatorExpression(UnaryOperatorType.Not, arg1);

31
ICSharpCode.Decompiler/ILAst/ILAstOptimizer.cs

@ -42,6 +42,7 @@ namespace ICSharpCode.Decompiler.ILAst
SimplifyTernaryOperator, SimplifyTernaryOperator,
SimplifyNullCoalescing, SimplifyNullCoalescing,
JoinBasicBlocks, JoinBasicBlocks,
SimplifyLogicNot,
TransformDecimalCtorToConstant, TransformDecimalCtorToConstant,
SimplifyLdObjAndStObj, SimplifyLdObjAndStObj,
TransformArrayInitializers, TransformArrayInitializers,
@ -129,6 +130,9 @@ namespace ICSharpCode.Decompiler.ILAst
if (abortBeforeStep == ILAstOptimizationStep.JoinBasicBlocks) return; if (abortBeforeStep == ILAstOptimizationStep.JoinBasicBlocks) return;
modified |= block.RunOptimization(new SimpleControlFlow(context, method).JoinBasicBlocks); modified |= block.RunOptimization(new SimpleControlFlow(context, method).JoinBasicBlocks);
if (abortBeforeStep == ILAstOptimizationStep.SimplifyLogicNot) return;
modified |= block.RunOptimization(SimplifyLogicNot);
if (abortBeforeStep == ILAstOptimizationStep.TransformDecimalCtorToConstant) return; if (abortBeforeStep == ILAstOptimizationStep.TransformDecimalCtorToConstant) return;
modified |= block.RunOptimization(TransformDecimalCtorToConstant); modified |= block.RunOptimization(TransformDecimalCtorToConstant);
@ -283,27 +287,30 @@ namespace ICSharpCode.Decompiler.ILAst
for (int i = 0; i < block.Body.Count; i++) { for (int i = 0; i < block.Body.Count; i++) {
ILExpression expr = block.Body[i] as ILExpression; ILExpression expr = block.Body[i] as ILExpression;
if (expr != null && expr.Prefixes == null) { if (expr != null && expr.Prefixes == null) {
ILCode op;
switch(expr.Code) { switch(expr.Code) {
case ILCode.Switch: case ILCode.Switch:
case ILCode.Brtrue: case ILCode.Brtrue:
expr.Arguments.Single().ILRanges.AddRange(expr.ILRanges); expr.Arguments.Single().ILRanges.AddRange(expr.ILRanges);
expr.ILRanges.Clear(); expr.ILRanges.Clear();
continue; continue;
case ILCode.__Brfalse: block.Body[i] = new ILExpression(ILCode.Brtrue, expr.Operand, new ILExpression(ILCode.LogicNot, null, expr.Arguments.Single())); break; case ILCode.__Brfalse: op = ILCode.LogicNot; break;
case ILCode.__Beq: block.Body[i] = new ILExpression(ILCode.Brtrue, expr.Operand, new ILExpression(ILCode.Ceq, null, expr.Arguments)); break; case ILCode.__Beq: op = ILCode.Ceq; break;
case ILCode.__Bne_Un: block.Body[i] = new ILExpression(ILCode.Brtrue, expr.Operand, new ILExpression(ILCode.LogicNot, null, new ILExpression(ILCode.Ceq, null, expr.Arguments))); break; case ILCode.__Bne_Un: op = ILCode.Cne; break;
case ILCode.__Bgt: block.Body[i] = new ILExpression(ILCode.Brtrue, expr.Operand, new ILExpression(ILCode.Cgt, null, expr.Arguments)); break; case ILCode.__Bgt: op = ILCode.Cgt; break;
case ILCode.__Bgt_Un: block.Body[i] = new ILExpression(ILCode.Brtrue, expr.Operand, new ILExpression(ILCode.Cgt_Un, null, expr.Arguments)); break; case ILCode.__Bgt_Un: op = ILCode.Cgt_Un; break;
case ILCode.__Ble: block.Body[i] = new ILExpression(ILCode.Brtrue, expr.Operand, new ILExpression(ILCode.LogicNot, null, new ILExpression(ILCode.Cgt, null, expr.Arguments))); break; case ILCode.__Ble: op = ILCode.Cle; break;
case ILCode.__Ble_Un: block.Body[i] = new ILExpression(ILCode.Brtrue, expr.Operand, new ILExpression(ILCode.LogicNot, null, new ILExpression(ILCode.Cgt_Un, null, expr.Arguments))); break; case ILCode.__Ble_Un: op = ILCode.Cle_Un; break;
case ILCode.__Blt: block.Body[i] = new ILExpression(ILCode.Brtrue, expr.Operand, new ILExpression(ILCode.Clt, null, expr.Arguments)); break; case ILCode.__Blt: op = ILCode.Clt; break;
case ILCode.__Blt_Un: block.Body[i] = new ILExpression(ILCode.Brtrue, expr.Operand, new ILExpression(ILCode.Clt_Un, null, expr.Arguments)); break; case ILCode.__Blt_Un: op = ILCode.Clt_Un; break;
case ILCode.__Bge: block.Body[i] = new ILExpression(ILCode.Brtrue, expr.Operand, new ILExpression(ILCode.LogicNot, null, new ILExpression(ILCode.Clt, null, expr.Arguments))); break; case ILCode.__Bge: op = ILCode.Cge; break;
case ILCode.__Bge_Un: block.Body[i] = new ILExpression(ILCode.Brtrue, expr.Operand, new ILExpression(ILCode.LogicNot, null, new ILExpression(ILCode.Clt_Un, null, expr.Arguments))); break; case ILCode.__Bge_Un: op = ILCode.Cge_Un; break;
default: default:
continue; continue;
} }
((ILExpression)block.Body[i]).Arguments.Single().ILRanges.AddRange(expr.ILRanges); var newExpr = new ILExpression(op, null, expr.Arguments);
block.Body[i] = new ILExpression(ILCode.Brtrue, expr.Operand, newExpr);
newExpr.ILRanges = expr.ILRanges;
} }
} }
} }

5
ICSharpCode.Decompiler/ILAst/ILCodes.cs

@ -247,6 +247,11 @@ namespace ICSharpCode.Decompiler.ILAst
Readonly, Readonly,
// Virtual codes - defined for convenience // Virtual codes - defined for convenience
Cne,
Cge,
Cge_Un,
Cle,
Cle_Un,
Ldexception, // Operand holds the CatchType for catch handler, null for filter Ldexception, // Operand holds the CatchType for catch handler, null for filter
LogicNot, LogicNot,
LogicAnd, LogicAnd,

89
ICSharpCode.Decompiler/ILAst/NullableOperators.cs

@ -96,11 +96,6 @@ namespace ICSharpCode.Decompiler.ILAst
{ {
return e.Code == this.code; return e.Code == this.code;
} }
public override ILExpression BuildNew(ref PatternMatcher pm, ILExpression[] args)
{
return new ILExpression(this.code, null, args);
}
} }
sealed class MethodPattern : Pattern sealed class MethodPattern : Pattern
@ -144,10 +139,17 @@ namespace ICSharpCode.Decompiler.ILAst
case ILCode.Ceq: case ILCode.Ceq:
if (!equals.GetValueOrDefault() || custom.GetValueOrDefault()) return false; if (!equals.GetValueOrDefault() || custom.GetValueOrDefault()) return false;
break; break;
case ILCode.Cne:
if (equals.GetValueOrDefault(true) || custom.GetValueOrDefault()) return false;
break;
case ILCode.Cgt: case ILCode.Cgt:
case ILCode.Cgt_Un: case ILCode.Cgt_Un:
case ILCode.Cge:
case ILCode.Cge_Un:
case ILCode.Clt: case ILCode.Clt:
case ILCode.Clt_Un: case ILCode.Clt_Un:
case ILCode.Cle:
case ILCode.Cle_Un:
if (equals != null || custom.GetValueOrDefault()) return false; if (equals != null || custom.GetValueOrDefault()) return false;
break; break;
case ILCode.Call: case ILCode.Call:
@ -219,37 +221,17 @@ namespace ICSharpCode.Decompiler.ILAst
} }
} }
sealed class PrimitivePattern : Pattern
{
readonly ILCode code;
readonly object operand;
public PrimitivePattern(ILCode code, object operand, params Pattern[] arguments)
: base(arguments)
{
this.code = code;
this.operand = operand;
}
public override bool Match(ref PatternMatcher pm, ILExpression e)
{
return e.Code == code && object.Equals(e.Operand, this.operand);
}
}
static readonly Tuple<string, string, string> GetValueOrDefault = new Tuple<string, string, string>("GetValueOrDefault", "Nullable`1", "System"); static readonly Tuple<string, string, string> GetValueOrDefault = new Tuple<string, string, string>("GetValueOrDefault", "Nullable`1", "System");
static readonly Tuple<string, string, string> get_HasValue = new Tuple<string, string, string>("get_HasValue", "Nullable`1", "System"); static readonly Tuple<string, string, string> get_HasValue = new Tuple<string, string, string>("get_HasValue", "Nullable`1", "System");
static readonly Pattern VariableRefA = new VariablePattern(ILCode.Ldloca, false), VariableRefB = new VariablePattern(ILCode.Ldloca, true); static readonly Pattern VariableRefA = new VariablePattern(ILCode.Ldloca, false), VariableRefB = new VariablePattern(ILCode.Ldloca, true);
static readonly Pattern VariableA = new VariablePattern(ILCode.Ldloc, false), VariableB = new VariablePattern(ILCode.Ldloc, true); static readonly Pattern VariableA = new VariablePattern(ILCode.Ldloc, false), VariableB = new VariablePattern(ILCode.Ldloc, true);
static readonly Pattern VariableAHasValue = new MethodPattern(ILCode.CallGetter, get_HasValue, VariableRefA); static readonly Pattern VariableAHasValue = new MethodPattern(ILCode.CallGetter, get_HasValue, VariableRefA);
static readonly Pattern VariableAGetValueOrDefault = new MethodPattern(ILCode.Call, GetValueOrDefault, VariableRefA); static readonly Pattern VariableAGetValueOrDefault = new MethodPattern(ILCode.Call, GetValueOrDefault, VariableRefA);
static readonly Pattern NotVariableAHasValue = new ILPattern(ILCode.Ceq, VariableAHasValue, new PrimitivePattern(ILCode.Ldc_I4, 0));
static readonly Pattern VariableBHasValue = new MethodPattern(ILCode.CallGetter, get_HasValue, VariableRefB); static readonly Pattern VariableBHasValue = new MethodPattern(ILCode.CallGetter, get_HasValue, VariableRefB);
static readonly Pattern VariableBGetValueOrDefault = new MethodPattern(ILCode.Call, GetValueOrDefault, VariableRefB); static readonly Pattern VariableBGetValueOrDefault = new MethodPattern(ILCode.Call, GetValueOrDefault, VariableRefB);
static readonly Pattern NotVariableBHasValue = new ILPattern(ILCode.Ceq, VariableBHasValue, new PrimitivePattern(ILCode.Ldc_I4, 0));
static readonly Pattern CeqHasValue = new ILPattern(ILCode.Ceq, VariableAHasValue, VariableBHasValue); static readonly Pattern CeqHasValue = new ILPattern(ILCode.Ceq, VariableAHasValue, VariableBHasValue);
static readonly Pattern CneHasValue = new ILPattern(ILCode.Cne, VariableAHasValue, VariableBHasValue);
static readonly Pattern AndHasValue = new ILPattern(ILCode.And, VariableAHasValue, VariableBHasValue); static readonly Pattern AndHasValue = new ILPattern(ILCode.And, VariableAHasValue, VariableBHasValue);
static readonly Pattern NotCeqHasValue = new ILPattern(ILCode.Ceq, CeqHasValue, new PrimitivePattern(ILCode.Ldc_I4, 0));
static readonly Pattern[] LoadValuesNN = new[] { VariableAGetValueOrDefault, VariableBGetValueOrDefault }; static readonly Pattern[] LoadValuesNN = new[] { VariableAGetValueOrDefault, VariableBGetValueOrDefault };
static OperatorPattern OperatorNN(bool? equals = null, bool? custom = null) static OperatorPattern OperatorNN(bool? equals = null, bool? custom = null)
@ -272,55 +254,43 @@ namespace ICSharpCode.Decompiler.ILAst
static readonly Pattern[] Comparisons = new Pattern[] { static readonly Pattern[] Comparisons = new Pattern[] {
/* both operands nullable */ /* both operands nullable */
// == (Primitive, Decimal) // == (Primitive, Decimal)
!!OperatorNN(equals: true) & CeqHasValue, OperatorNN(equals: true) & CeqHasValue,
// == (Struct) // == (Struct)
!!CeqHasValue & (!VariableAHasValue | OperatorNN(equals: true, custom: true)), CeqHasValue & (!VariableAHasValue | OperatorNN(equals: true, custom: true)),
// != (Primitive) // != (Primitive, Decimal)
!OperatorNN(equals: true, custom: false) | NotCeqHasValue, OperatorNN(equals: false) | CneHasValue,
// != (Decimal)
OperatorNN(equals: false, custom: true) | NotCeqHasValue,
// != (Struct) // != (Struct)
!CeqHasValue | (!!VariableAHasValue & OperatorNN(equals: false, custom: true)), CneHasValue | (VariableAHasValue & OperatorNN(equals: false, custom: true)),
// > , < (Primitive, Decimal), >= , <= (Decimal) // > , < , >= , <= (Primitive, Decimal)
!!OperatorNN() & AndHasValue, OperatorNN() & AndHasValue,
// >= , <= (Primitive)
!OperatorNN(custom: false) & AndHasValue,
// > , < , >= , <= (Struct) // > , < , >= , <= (Struct)
AndHasValue & OperatorNN(custom: true), AndHasValue & OperatorNN(custom: true),
/* only first operand nullable */ /* only first operand nullable */
// == (Primitive, Decimal) // == (Primitive, Decimal)
!!OperatorNV(equals: true) & VariableAHasValue, OperatorNV(equals: true) & VariableAHasValue,
// == (Struct) // == (Struct)
!!VariableAHasValue & OperatorNV(equals: true, custom: true), VariableAHasValue & OperatorNV(equals: true, custom: true),
// != (Primitive) // != (Primitive, Decimal)
!OperatorNV(equals: true, custom: false) | NotVariableAHasValue, OperatorNV(equals: false) | !VariableAHasValue,
// != (Decimal)
OperatorNV(equals: false, custom: true) | NotVariableAHasValue,
// != (Struct) // != (Struct)
!VariableAHasValue | OperatorNV(equals: false, custom: true), !VariableAHasValue | OperatorNV(equals: false, custom: true),
// > , < (Primitive, Decimal), >= , <= (Decimal) // > , <, >= , <= (Primitive, Decimal)
!!OperatorNV() & VariableAHasValue, OperatorNV() & VariableAHasValue,
// >= , <= (Primitive)
!OperatorNV(custom: false) & VariableAHasValue,
// > , < , >= , <= (Struct) // > , < , >= , <= (Struct)
VariableAHasValue & OperatorNV(custom: true), VariableAHasValue & OperatorNV(custom: true),
/* only second operand nullable */ /* only second operand nullable */
// == (Primitive, Decimal) // == (Primitive, Decimal)
!!OperatorVN(equals: true) & VariableBHasValue, OperatorVN(equals: true) & VariableBHasValue,
// == (Struct) // == (Struct)
!!VariableBHasValue & OperatorVN(equals: true, custom: true), VariableBHasValue & OperatorVN(equals: true, custom: true),
// != (Primitive) // != (Primitive, Decimal)
!OperatorVN(equals: true, custom: false) | NotVariableBHasValue, OperatorVN(equals: false) | !VariableBHasValue,
// != (Decimal)
OperatorVN(equals: false, custom: true) | NotVariableBHasValue,
// != (Struct) // != (Struct)
!VariableBHasValue | OperatorVN(equals: false, custom: true), !VariableBHasValue | OperatorVN(equals: false, custom: true),
// > , < (Primitive, Decimal), >= , <= (Decimal) // > , <, >= , <= (Primitive, Decimal)
!!OperatorVN() & VariableBHasValue, OperatorVN() & VariableBHasValue,
// >= , <= (Primitive)
!OperatorVN(custom: false) & VariableBHasValue,
// > , < , >= , <= (Struct) // > , < , >= , <= (Struct)
VariableBHasValue & OperatorVN(custom: true), VariableBHasValue & OperatorVN(custom: true),
}; };
@ -345,7 +315,6 @@ namespace ICSharpCode.Decompiler.ILAst
} }
static readonly Pattern OperatorVariableAB = new OperatorPattern(VariableA, VariableB); static readonly Pattern OperatorVariableAB = new OperatorPattern(VariableA, VariableB);
static readonly Pattern NotOperatorVariableAB = !OperatorVariableAB;
public static bool Simplify(ILExpression expr) public static bool Simplify(ILExpression expr)
{ {
@ -355,12 +324,12 @@ namespace ICSharpCode.Decompiler.ILAst
for (int i = 0; i < ps.Length; i++) { for (int i = 0; i < ps.Length; i++) {
var pm = new PatternMatcher(); var pm = new PatternMatcher();
if (!pm.Match(ps[i], expr)) continue; if (!pm.Match(ps[i], expr)) continue;
var pi = i % 8; var n = pm.BuildNew(OperatorVariableAB, expr);
var n = pm.BuildNew(pi != 2 && pi != 6 ? OperatorVariableAB : NotOperatorVariableAB, expr);
expr.Code = n.Code; expr.Code = n.Code;
expr.Operand = n.Operand; expr.Operand = n.Operand;
expr.Arguments = n.Arguments; expr.Arguments = n.Arguments;
expr.ILRanges = n.ILRanges; expr.ILRanges = n.ILRanges;
expr.InferredType = n.InferredType;
return true; return true;
} }
return false; return false;

60
ICSharpCode.Decompiler/ILAst/PeepholeTransform.cs

@ -821,5 +821,65 @@ namespace ICSharpCode.Decompiler.ILAst
return false; return false;
} }
#endregion #endregion
#region SimplifyLogicNot
static bool SimplifyLogicNot(List<ILNode> body, ILExpression expr, int pos)
{
bool modified = false;
expr = SimplifyLogicNot(expr, ref modified);
Debug.Assert(expr == null);
return modified;
}
static ILExpression SimplifyLogicNot(ILExpression expr, ref bool modified)
{
if (expr.Code == ILCode.Ceq) {
var a = expr.Arguments[1];
if (a.Code == ILCode.Ldc_I4 && TypeAnalysis.IsBoolean(a.InferredType) && TypeAnalysis.IsBoolean(expr.Arguments[0].InferredType)) {
expr.Code = ILCode.LogicNot;
expr.ILRanges.AddRange(a.ILRanges);
expr.Arguments.RemoveAt(1);
modified = true;
}
}
ILExpression res = null;
while (expr.Code == ILCode.LogicNot) {
var a = expr.Arguments[0];
ILCode c = 0;
switch (a.Code) {
case ILCode.LogicNot:
res = a.Arguments[0];
res.ILRanges.AddRange(expr.ILRanges);
res.ILRanges.AddRange(a.ILRanges);
expr = res;
continue;
case ILCode.Ceq: c = ILCode.Cne; break;
case ILCode.Cne: c = ILCode.Ceq; break;
case ILCode.Cgt: c = ILCode.Cle; break;
case ILCode.Cgt_Un: c = ILCode.Cle_Un; break;
case ILCode.Cge: c = ILCode.Clt; break;
case ILCode.Cge_Un: c = ILCode.Clt_Un; break;
case ILCode.Clt: c = ILCode.Cge; break;
case ILCode.Clt_Un: c = ILCode.Cge_Un; break;
case ILCode.Cle: c = ILCode.Cgt; break;
case ILCode.Cle_Un: c = ILCode.Cgt_Un; break;
}
if (c == 0) break;
res = a;
res.Code = c;
res.ILRanges.AddRange(expr.ILRanges);
expr = res;
break;
}
for (int i = 0; i < expr.Arguments.Count; i++) {
var a = SimplifyLogicNot(expr.Arguments[i], ref modified);
if (a != null) {
expr.Arguments[i] = a;
modified = true;
}
}
return res;
}
#endregion
} }
} }

10
ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

@ -292,7 +292,10 @@ namespace ICSharpCode.Decompiler.ILAst
ILVariable v = (ILVariable)expr.Operand; ILVariable v = (ILVariable)expr.Operand;
if (forceInferChildren) { if (forceInferChildren) {
// do not use 'expectedType' in here! // do not use 'expectedType' in here!
InferTypeForExpression(expr.Arguments.Single(), v.Type); var arg = expr.Arguments.Single();
InferTypeForExpression(arg, v.Type);
// there is no conversion from int to bool in C# and ldc.i4.0/ldc.i4.1 is used for variable initialization and logic negations (this needs a better solution - a new pass with the fixed variable type)
if (IsBoolean(arg.InferredType) && v.Type.MetadataType == MetadataType.Int32) v.Type = arg.ExpectedType = arg.InferredType;
} }
return v.Type; return v.Type;
} }
@ -691,16 +694,21 @@ namespace ICSharpCode.Decompiler.ILAst
#endregion #endregion
#region Comparison instructions #region Comparison instructions
case ILCode.Ceq: case ILCode.Ceq:
case ILCode.Cne:
if (forceInferChildren) if (forceInferChildren)
InferArgumentsInBinaryOperator(expr, null, null); InferArgumentsInBinaryOperator(expr, null, null);
return typeSystem.Boolean; return typeSystem.Boolean;
case ILCode.Clt: case ILCode.Clt:
case ILCode.Cgt: case ILCode.Cgt:
case ILCode.Cle:
case ILCode.Cge:
if (forceInferChildren) if (forceInferChildren)
InferArgumentsInBinaryOperator(expr, true, null); InferArgumentsInBinaryOperator(expr, true, null);
return typeSystem.Boolean; return typeSystem.Boolean;
case ILCode.Clt_Un: case ILCode.Clt_Un:
case ILCode.Cgt_Un: case ILCode.Cgt_Un:
case ILCode.Cle_Un:
case ILCode.Cge_Un:
if (forceInferChildren) if (forceInferChildren)
InferArgumentsInBinaryOperator(expr, false, null); InferArgumentsInBinaryOperator(expr, false, null);
return typeSystem.Boolean; return typeSystem.Boolean;

3
ICSharpCode.Decompiler/ILAst/YieldReturnDecompiler.cs

@ -634,13 +634,14 @@ namespace ICSharpCode.Decompiler.ILAst
case ILCode.Ldc_I4: case ILCode.Ldc_I4:
return new SymbolicValue(SymbolicValueType.IntegerConstant, (int)expr.Operand); return new SymbolicValue(SymbolicValueType.IntegerConstant, (int)expr.Operand);
case ILCode.Ceq: case ILCode.Ceq:
case ILCode.Cne:
left = Eval(expr.Arguments[0]); left = Eval(expr.Arguments[0]);
right = Eval(expr.Arguments[1]); right = Eval(expr.Arguments[1]);
if (left.Type != SymbolicValueType.State || right.Type != SymbolicValueType.IntegerConstant) if (left.Type != SymbolicValueType.State || right.Type != SymbolicValueType.IntegerConstant)
throw new YieldAnalysisFailedException(); throw new YieldAnalysisFailedException();
// bool: (state + left.Constant == right.Constant) // bool: (state + left.Constant == right.Constant)
// bool: (state == right.Constant - left.Constant) // bool: (state == right.Constant - left.Constant)
return new SymbolicValue(SymbolicValueType.StateEquals, unchecked ( right.Constant - left.Constant )); return new SymbolicValue(expr.Code == ILCode.Ceq ? SymbolicValueType.StateEquals : SymbolicValueType.StateInEquals, unchecked(right.Constant - left.Constant));
case ILCode.LogicNot: case ILCode.LogicNot:
SymbolicValue val = Eval(expr.Arguments[0]); SymbolicValue val = Eval(expr.Arguments[0]);
if (val.Type == SymbolicValueType.StateEquals) if (val.Type == SymbolicValueType.StateEquals)

Loading…
Cancel
Save