Browse Source

Add comparisons with 0 or null if necessary. Closes #8.

pull/37/head
Daniel Grunwald 15 years ago
parent
commit
798d156670
  1. 47
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  2. 25
      ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

47
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -235,19 +235,42 @@ namespace Decompiler
List<Ast.Expression> args = TransformExpressionArguments(expr); List<Ast.Expression> args = TransformExpressionArguments(expr);
Ast.Expression arg1 = args.Count >= 1 ? args[0] : null; Ast.Expression arg1 = args.Count >= 1 ? args[0] : null;
Ast.Expression arg2 = args.Count >= 2 ? args[1] : null; Ast.Expression arg2 = args.Count >= 2 ? args[1] : null;
TypeReference arg1Type = args.Count >= 1 ? expr.Arguments[0].InferredType : null;
switch(expr.OpCode.Code) { switch(expr.OpCode.Code) {
case Code.Brfalse: return new Ast.UnaryOperatorExpression(UnaryOperatorType.Not, arg1); case Code.Brfalse:
case Code.Brtrue: return arg1; if (arg1Type == typeSystem.Boolean)
case Code.Beq: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, arg2); return new Ast.UnaryOperatorExpression(UnaryOperatorType.Not, arg1);
case Code.Bge: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2); else if (TypeAnalysis.IsIntegerOrEnum(typeSystem, arg1Type))
case Code.Bge_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2); return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, new PrimitiveExpression(0));
case Code.Bgt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2); else
case Code.Bgt_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2); return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, new NullReferenceExpression());
case Code.Ble: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2); case Code.Brtrue:
case Code.Ble_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2); if (arg1Type == typeSystem.Boolean)
case Code.Blt: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2); return arg1;
case Code.Blt_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2); else if (TypeAnalysis.IsIntegerOrEnum(typeSystem, arg1Type))
case Code.Bne_Un: return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, arg2); return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, new PrimitiveExpression(0));
else
return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, new NullReferenceExpression());
case Code.Beq:
return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, arg2);
case Code.Bge:
return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2);
case Code.Bge_Un:
return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThanOrEqual, arg2);
case Code.Bgt:
return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2);
case Code.Bgt_Un:
return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.GreaterThan, arg2);
case Code.Ble:
return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2);
case Code.Ble_Un:
return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThanOrEqual, arg2);
case Code.Blt:
return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2);
case Code.Blt_Un:
return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.LessThan, arg2);
case Code.Bne_Un:
return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.InEquality, arg2);
default: throw new Exception("Bad opcode"); default: throw new Exception("Bad opcode");
} }
/* /*

25
ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

@ -99,6 +99,10 @@ namespace Decompiler
} }
return ctor.DeclaringType; return ctor.DeclaringType;
} }
case Code.Ldfld:
return UnpackModifiers(((FieldReference)expr.Operand).FieldType);
case Code.Ldsfld:
return UnpackModifiers(((FieldReference)expr.Operand).FieldType);
case Code.Or: case Code.Or:
return InferArgumentsInBinaryOperator(expr); return InferArgumentsInBinaryOperator(expr);
case Code.Shl: case Code.Shl:
@ -107,9 +111,9 @@ namespace Decompiler
InferTypeForExpression(expr.Arguments[1], typeSystem.Int32); InferTypeForExpression(expr.Arguments[1], typeSystem.Int32);
return InferTypeForExpression(expr.Arguments[0], expectedType); return InferTypeForExpression(expr.Arguments[0], expectedType);
case Code.Ldc_I4: case Code.Ldc_I4:
return (IsSigned(expectedType) != null || expectedType == typeSystem.Boolean) ? expectedType : typeSystem.Int32; return (IsIntegerOrEnum(expectedType) || expectedType == typeSystem.Boolean) ? expectedType : typeSystem.Int32;
case Code.Ldc_I8: case Code.Ldc_I8:
return (IsSigned(expectedType) != null) ? expectedType : typeSystem.Int64; return (IsIntegerOrEnum(expectedType)) ? expectedType : typeSystem.Int64;
case Code.Conv_I8: case Code.Conv_I8:
return (GetInformationAmount(expectedType) == 64 && IsSigned(expectedType) == true) ? expectedType : typeSystem.Int64; return (GetInformationAmount(expectedType) == 64 && IsSigned(expectedType) == true) ? expectedType : typeSystem.Int64;
case Code.Dup: case Code.Dup:
@ -135,6 +139,13 @@ namespace Decompiler
} }
} }
static TypeReference UnpackModifiers(TypeReference type)
{
while (type is OptionalModifierType || type is RequiredModifierType)
type = ((TypeSpecification)type).ElementType;
return type;
}
TypeReference InferArgumentsInBinaryOperator(ILExpression expr) TypeReference InferArgumentsInBinaryOperator(ILExpression expr)
{ {
ILExpression left = expr.Arguments[0]; ILExpression left = expr.Arguments[0];
@ -194,6 +205,16 @@ namespace Decompiler
return 100; // we consider structs/objects to have more information than any primitives return 100; // we consider structs/objects to have more information than any primitives
} }
bool IsIntegerOrEnum(TypeReference type)
{
return IsIntegerOrEnum(typeSystem, type);
}
public static bool IsIntegerOrEnum(TypeSystem typeSystem, TypeReference type)
{
return IsSigned(typeSystem, type) != null;
}
bool? IsSigned(TypeReference type) bool? IsSigned(TypeReference type)
{ {
return IsSigned(typeSystem, type); return IsSigned(typeSystem, type);

Loading…
Cancel
Save