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 @@ -235,19 +235,42 @@ namespace Decompiler
List<Ast.Expression> args = TransformExpressionArguments(expr);
Ast.Expression arg1 = args.Count >= 1 ? args[0] : null;
Ast.Expression arg2 = args.Count >= 2 ? args[1] : null;
TypeReference arg1Type = args.Count >= 1 ? expr.Arguments[0].InferredType : null;
switch(expr.OpCode.Code) {
case Code.Brfalse: return new Ast.UnaryOperatorExpression(UnaryOperatorType.Not, arg1);
case Code.Brtrue: return arg1;
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);
case Code.Brfalse:
if (arg1Type == typeSystem.Boolean)
return new Ast.UnaryOperatorExpression(UnaryOperatorType.Not, arg1);
else if (TypeAnalysis.IsIntegerOrEnum(typeSystem, arg1Type))
return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, new PrimitiveExpression(0));
else
return new Ast.BinaryOperatorExpression(arg1, BinaryOperatorType.Equality, new NullReferenceExpression());
case Code.Brtrue:
if (arg1Type == typeSystem.Boolean)
return arg1;
else if (TypeAnalysis.IsIntegerOrEnum(typeSystem, arg1Type))
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");
}
/*

25
ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

@ -99,6 +99,10 @@ namespace Decompiler @@ -99,6 +99,10 @@ namespace Decompiler
}
return ctor.DeclaringType;
}
case Code.Ldfld:
return UnpackModifiers(((FieldReference)expr.Operand).FieldType);
case Code.Ldsfld:
return UnpackModifiers(((FieldReference)expr.Operand).FieldType);
case Code.Or:
return InferArgumentsInBinaryOperator(expr);
case Code.Shl:
@ -107,9 +111,9 @@ namespace Decompiler @@ -107,9 +111,9 @@ namespace Decompiler
InferTypeForExpression(expr.Arguments[1], typeSystem.Int32);
return InferTypeForExpression(expr.Arguments[0], expectedType);
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:
return (IsSigned(expectedType) != null) ? expectedType : typeSystem.Int64;
return (IsIntegerOrEnum(expectedType)) ? expectedType : typeSystem.Int64;
case Code.Conv_I8:
return (GetInformationAmount(expectedType) == 64 && IsSigned(expectedType) == true) ? expectedType : typeSystem.Int64;
case Code.Dup:
@ -135,6 +139,13 @@ namespace Decompiler @@ -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)
{
ILExpression left = expr.Arguments[0];
@ -194,6 +205,16 @@ namespace Decompiler @@ -194,6 +205,16 @@ namespace Decompiler
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)
{
return IsSigned(typeSystem, type);

Loading…
Cancel
Save