From c8f8d9ef4e9e343185c666c2d40c49fefa5a1ee2 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 30 May 2015 20:39:40 +0200 Subject: [PATCH] improve conversion of Ceq-ILAst instruction --- .../CSharp/ExpressionBuilder.cs | 10 ++- .../CSharp/TranslatedExpression.cs | 5 ++ .../ICSharpCode.Decompiler.csproj | 1 + .../TypeSystem/DecompilerTypeSystemUtils.cs | 63 +++++++++++++++++++ 4 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystemUtils.cs diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 718ee17ab..acb02edaf 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -247,7 +247,15 @@ namespace ICSharpCode.Decompiler.CSharp var rr = resolver.ResolveBinaryOperator(BinaryOperatorType.Equality, left.ResolveResult, right.ResolveResult); if (rr.IsError) { - // TODO: insert casts to the wider type of the two input types + var targetType = DecompilerTypeSystemUtils.GetLargerType(left.Type, right.Type); + if (targetType.Equals(left.Type)) { + right = right.ConvertTo(targetType, this); + } else { + left = left.ConvertTo(targetType, this); + } + rr = new OperatorResolveResult(compilation.FindType(KnownTypeCode.Boolean), + BinaryOperatorExpression.GetLinqNodeType(BinaryOperatorType.Equality, false), + left.ResolveResult, right.ResolveResult); } return new BinaryOperatorExpression(left.Expression, BinaryOperatorType.Equality, right.Expression) .WithILInstruction(inst) diff --git a/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs b/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs index 3aafde82b..1a577b6db 100644 --- a/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs @@ -175,6 +175,11 @@ namespace ICSharpCode.Decompiler.CSharp return expressionBuilder.ConvertConstantValue(rr) .WithILInstruction(this.ILInstructions); } + if (targetType.Kind == TypeKind.Pointer && 0.Equals(ResolveResult.ConstantValue)) { + return new NullReferenceExpression() + .WithILInstruction(this.ILInstructions) + .WithRR(new ConstantResolveResult(targetType, null)); + } return Expression.CastTo(expressionBuilder.ConvertType(targetType)) .WithoutILInstruction().WithRR(rr); } diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index c18756103..2f03403fb 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -135,6 +135,7 @@ + diff --git a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystemUtils.cs b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystemUtils.cs new file mode 100644 index 000000000..311c8e0a4 --- /dev/null +++ b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystemUtils.cs @@ -0,0 +1,63 @@ +// Copyright (c) 2015 Siegfried Pammer +// +// 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 +{ + public static class DecompilerTypeSystemUtils + { + static int GetNativeSize(IType type) + { + if (type.Kind == TypeKind.Pointer) + return 6; + + var typeForConstant = (type.Kind == TypeKind.Enum) ? type.GetDefinition().EnumUnderlyingType : type; + var typeDef = typeForConstant.GetDefinition(); + if (typeDef == null) + return 0; + switch (typeDef.KnownTypeCode) { + case KnownTypeCode.Boolean: + case KnownTypeCode.SByte: + case KnownTypeCode.Byte: + return 1; + case KnownTypeCode.Char: + case KnownTypeCode.Int16: + case KnownTypeCode.UInt16: + return 2; + case KnownTypeCode.Int32: + case KnownTypeCode.UInt32: + case KnownTypeCode.Single: + return 4; + case KnownTypeCode.IntPtr: + case KnownTypeCode.UIntPtr: + return 6; + case KnownTypeCode.Int64: + case KnownTypeCode.UInt64: + case KnownTypeCode.Double: + return 8; + } + return 0; + } + + public static IType GetLargerType(IType type1, IType type2) + { + return GetNativeSize(type1) >= GetNativeSize(type2) ? type1 : type2; + } + } +}