mirror of https://github.com/icsharpcode/ILSpy.git
10 changed files with 341 additions and 563 deletions
@ -1,164 +0,0 @@ |
|||||||
// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
|
|
||||||
//
|
|
||||||
// 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 System.Collections.Generic; |
|
||||||
using System.Linq; |
|
||||||
using ICSharpCode.NRefactory.CSharp; |
|
||||||
using ICSharpCode.NRefactory.PatternMatching; |
|
||||||
|
|
||||||
namespace ICSharpCode.Decompiler.CSharp.Transforms |
|
||||||
{ |
|
||||||
public class PushNegation: DepthFirstAstVisitor<object, object>, IAstTransform |
|
||||||
{ |
|
||||||
sealed class LiftedOperator { } |
|
||||||
/// <summary>
|
|
||||||
/// Annotation for lifted operators that cannot be transformed by PushNegation
|
|
||||||
/// </summary>
|
|
||||||
public static readonly object LiftedOperatorAnnotation = new LiftedOperator(); |
|
||||||
|
|
||||||
public override object VisitUnaryOperatorExpression(UnaryOperatorExpression unary, object data) |
|
||||||
{ |
|
||||||
// lifted operators can't be transformed
|
|
||||||
if (unary.Annotation<LiftedOperator>() != null || unary.Expression.Annotation<LiftedOperator>() != null) |
|
||||||
return base.VisitUnaryOperatorExpression(unary, data); |
|
||||||
|
|
||||||
// Remove double negation
|
|
||||||
// !!a
|
|
||||||
if (unary.Operator == UnaryOperatorType.Not && |
|
||||||
unary.Expression is UnaryOperatorExpression && |
|
||||||
(unary.Expression as UnaryOperatorExpression).Operator == UnaryOperatorType.Not) |
|
||||||
{ |
|
||||||
AstNode newNode = (unary.Expression as UnaryOperatorExpression).Expression; |
|
||||||
unary.ReplaceWith(newNode); |
|
||||||
return newNode.AcceptVisitor(this, data); |
|
||||||
} |
|
||||||
|
|
||||||
// Push through binary operation
|
|
||||||
// !((a) op (b))
|
|
||||||
BinaryOperatorExpression binaryOp = unary.Expression as BinaryOperatorExpression; |
|
||||||
if (unary.Operator == UnaryOperatorType.Not && binaryOp != null) { |
|
||||||
bool successful = true; |
|
||||||
switch (binaryOp.Operator) { |
|
||||||
case BinaryOperatorType.Equality: |
|
||||||
binaryOp.Operator = BinaryOperatorType.InEquality; |
|
||||||
break; |
|
||||||
case BinaryOperatorType.InEquality: |
|
||||||
binaryOp.Operator = BinaryOperatorType.Equality; |
|
||||||
break; |
|
||||||
case BinaryOperatorType.GreaterThan: // TODO: these are invalid for floats (stupid NaN)
|
|
||||||
binaryOp.Operator = BinaryOperatorType.LessThanOrEqual; |
|
||||||
break; |
|
||||||
case BinaryOperatorType.GreaterThanOrEqual: |
|
||||||
binaryOp.Operator = BinaryOperatorType.LessThan; |
|
||||||
break; |
|
||||||
case BinaryOperatorType.LessThanOrEqual: |
|
||||||
binaryOp.Operator = BinaryOperatorType.GreaterThan; |
|
||||||
break; |
|
||||||
case BinaryOperatorType.LessThan: |
|
||||||
binaryOp.Operator = BinaryOperatorType.GreaterThanOrEqual; |
|
||||||
break; |
|
||||||
default: |
|
||||||
successful = false; |
|
||||||
break; |
|
||||||
} |
|
||||||
if (successful) { |
|
||||||
unary.ReplaceWith(binaryOp); |
|
||||||
return binaryOp.AcceptVisitor(this, data); |
|
||||||
} |
|
||||||
|
|
||||||
successful = true; |
|
||||||
switch (binaryOp.Operator) { |
|
||||||
case BinaryOperatorType.ConditionalAnd: |
|
||||||
binaryOp.Operator = BinaryOperatorType.ConditionalOr; |
|
||||||
break; |
|
||||||
case BinaryOperatorType.ConditionalOr: |
|
||||||
binaryOp.Operator = BinaryOperatorType.ConditionalAnd; |
|
||||||
break; |
|
||||||
default: |
|
||||||
successful = false; |
|
||||||
break; |
|
||||||
} |
|
||||||
if (successful) { |
|
||||||
binaryOp.Left.ReplaceWith(e => new UnaryOperatorExpression(UnaryOperatorType.Not, e)); |
|
||||||
binaryOp.Right.ReplaceWith(e => new UnaryOperatorExpression(UnaryOperatorType.Not, e)); |
|
||||||
unary.ReplaceWith(binaryOp); |
|
||||||
return binaryOp.AcceptVisitor(this, data); |
|
||||||
} |
|
||||||
} |
|
||||||
return base.VisitUnaryOperatorExpression(unary, data); |
|
||||||
} |
|
||||||
|
|
||||||
readonly static AstNode asCastIsNullPattern = new BinaryOperatorExpression( |
|
||||||
new AnyNode("expr").ToExpression().CastAs(new AnyNode("type")), |
|
||||||
BinaryOperatorType.Equality, |
|
||||||
new NullReferenceExpression() |
|
||||||
); |
|
||||||
|
|
||||||
readonly static AstNode asCastIsNotNullPattern = new BinaryOperatorExpression( |
|
||||||
new AnyNode("expr").ToExpression().CastAs(new AnyNode("type")), |
|
||||||
BinaryOperatorType.InEquality, |
|
||||||
new NullReferenceExpression() |
|
||||||
); |
|
||||||
|
|
||||||
public override object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data) |
|
||||||
{ |
|
||||||
// lifted operators can't be transformed
|
|
||||||
if (binaryOperatorExpression.Annotation<LiftedOperator>() != null) |
|
||||||
return base.VisitBinaryOperatorExpression(binaryOperatorExpression, data); |
|
||||||
|
|
||||||
BinaryOperatorType op = binaryOperatorExpression.Operator; |
|
||||||
bool? rightOperand = null; |
|
||||||
if (binaryOperatorExpression.Right is PrimitiveExpression) |
|
||||||
rightOperand = ((PrimitiveExpression)binaryOperatorExpression.Right).Value as bool?; |
|
||||||
if (op == BinaryOperatorType.Equality && rightOperand == true || op == BinaryOperatorType.InEquality && rightOperand == false) { |
|
||||||
// 'b == true' or 'b != false' is useless
|
|
||||||
binaryOperatorExpression.Left.AcceptVisitor(this, data); |
|
||||||
binaryOperatorExpression.ReplaceWith(binaryOperatorExpression.Left); |
|
||||||
return null; |
|
||||||
} else if (op == BinaryOperatorType.Equality && rightOperand == false || op == BinaryOperatorType.InEquality && rightOperand == true) { |
|
||||||
// 'b == false' or 'b != true' is a negation:
|
|
||||||
Expression left = binaryOperatorExpression.Left; |
|
||||||
left.Remove(); |
|
||||||
UnaryOperatorExpression uoe = new UnaryOperatorExpression(UnaryOperatorType.Not, left); |
|
||||||
binaryOperatorExpression.ReplaceWith(uoe); |
|
||||||
return uoe.AcceptVisitor(this, data); |
|
||||||
} else { |
|
||||||
bool negate = false; |
|
||||||
Match m = asCastIsNotNullPattern.Match(binaryOperatorExpression); |
|
||||||
if (!m.Success) { |
|
||||||
m = asCastIsNullPattern.Match(binaryOperatorExpression); |
|
||||||
negate = true; |
|
||||||
} |
|
||||||
if (m.Success) { |
|
||||||
Expression expr = m.Get<Expression>("expr").Single().Detach().IsType(m.Get<AstType>("type").Single().Detach()); |
|
||||||
if (negate) |
|
||||||
expr = new UnaryOperatorExpression(UnaryOperatorType.Not, expr); |
|
||||||
binaryOperatorExpression.ReplaceWith(expr); |
|
||||||
return expr.AcceptVisitor(this, data); |
|
||||||
} else { |
|
||||||
return base.VisitBinaryOperatorExpression(binaryOperatorExpression, data); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
void IAstTransform.Run(AstNode node) |
|
||||||
{ |
|
||||||
node.AcceptVisitor(this, null); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,64 +0,0 @@ |
|||||||
// 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 System.Collections.Generic; |
|
||||||
using System.Diagnostics; |
|
||||||
using System.Linq; |
|
||||||
using System.Text; |
|
||||||
using System.Threading.Tasks; |
|
||||||
namespace ICSharpCode.Decompiler.IL |
|
||||||
{ |
|
||||||
public abstract partial class BinaryComparisonInstruction : BinaryInstruction |
|
||||||
{ |
|
||||||
public readonly StackType OpType; |
|
||||||
|
|
||||||
protected BinaryComparisonInstruction(OpCode opCode, ILInstruction left, ILInstruction right) : base(opCode, left, right) |
|
||||||
{ |
|
||||||
this.OpType = ComputeOpType(left.ResultType, right.ResultType); |
|
||||||
} |
|
||||||
|
|
||||||
static StackType ComputeOpType(StackType left, StackType right) |
|
||||||
{ |
|
||||||
if (left == StackType.I || right == StackType.I) |
|
||||||
return StackType.I; |
|
||||||
Debug.Assert(left == right); |
|
||||||
return left; |
|
||||||
} |
|
||||||
|
|
||||||
public sealed override StackType ResultType { |
|
||||||
get { |
|
||||||
return StackType.I4; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public override void WriteTo(ITextOutput output) |
|
||||||
{ |
|
||||||
output.Write(OpCode); |
|
||||||
output.Write('.'); |
|
||||||
output.Write(OpType); |
|
||||||
output.Write('('); |
|
||||||
Left.WriteTo(output); |
|
||||||
output.Write(", "); |
|
||||||
Right.WriteTo(output); |
|
||||||
output.Write(')'); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
|
|
@ -0,0 +1,155 @@ |
|||||||
|
// 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 System.Diagnostics; |
||||||
|
using System.Linq; |
||||||
|
using ICSharpCode.NRefactory.CSharp; |
||||||
|
namespace ICSharpCode.Decompiler.IL |
||||||
|
{ |
||||||
|
public enum ComparisonKind : byte |
||||||
|
{ |
||||||
|
Equality, |
||||||
|
Inequality, |
||||||
|
LessThan, |
||||||
|
LessThanOrEqual, |
||||||
|
GreaterThan, |
||||||
|
GreaterThanOrEqual |
||||||
|
} |
||||||
|
|
||||||
|
static class ComparisonKindExtensions |
||||||
|
{ |
||||||
|
public static bool IsEqualityOrInequality(this ComparisonKind kind) |
||||||
|
{ |
||||||
|
return kind == ComparisonKind.Equality || kind == ComparisonKind.Inequality; |
||||||
|
} |
||||||
|
|
||||||
|
public static ComparisonKind Negate(this ComparisonKind kind) |
||||||
|
{ |
||||||
|
switch (kind) { |
||||||
|
case ComparisonKind.Equality: |
||||||
|
return ComparisonKind.Inequality; |
||||||
|
case ComparisonKind.Inequality: |
||||||
|
return ComparisonKind.Equality; |
||||||
|
case ComparisonKind.LessThan: |
||||||
|
return ComparisonKind.GreaterThanOrEqual; |
||||||
|
case ComparisonKind.LessThanOrEqual: |
||||||
|
return ComparisonKind.GreaterThan; |
||||||
|
case ComparisonKind.GreaterThan: |
||||||
|
return ComparisonKind.LessThanOrEqual; |
||||||
|
case ComparisonKind.GreaterThanOrEqual: |
||||||
|
return ComparisonKind.LessThan; |
||||||
|
default: |
||||||
|
throw new NotSupportedException(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static BinaryOperatorType ToBinaryOperatorType(this ComparisonKind kind) |
||||||
|
{ |
||||||
|
switch (kind) { |
||||||
|
case ComparisonKind.Equality: |
||||||
|
return BinaryOperatorType.Equality; |
||||||
|
case ComparisonKind.Inequality: |
||||||
|
return BinaryOperatorType.InEquality; |
||||||
|
case ComparisonKind.LessThan: |
||||||
|
return BinaryOperatorType.LessThan; |
||||||
|
case ComparisonKind.LessThanOrEqual: |
||||||
|
return BinaryOperatorType.LessThanOrEqual; |
||||||
|
case ComparisonKind.GreaterThan: |
||||||
|
return BinaryOperatorType.GreaterThan; |
||||||
|
case ComparisonKind.GreaterThanOrEqual: |
||||||
|
return BinaryOperatorType.GreaterThanOrEqual; |
||||||
|
default: |
||||||
|
throw new NotSupportedException(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static string GetToken(this ComparisonKind kind) |
||||||
|
{ |
||||||
|
return BinaryOperatorExpression.GetOperatorRole(kind.ToBinaryOperatorType()).Token; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
partial class Comp |
||||||
|
{ |
||||||
|
ComparisonKind kind; |
||||||
|
|
||||||
|
public ComparisonKind Kind { |
||||||
|
get { return kind; } |
||||||
|
set { |
||||||
|
kind = value; |
||||||
|
MakeDirty(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
StackType inputType; |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the stack type of the comparison inputs.
|
||||||
|
/// </summary>
|
||||||
|
public StackType InputType { |
||||||
|
get { return inputType; } |
||||||
|
set { |
||||||
|
inputType = value; |
||||||
|
MakeDirty(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If this is an integer comparison, specifies the sign used to interpret the integers.
|
||||||
|
/// </summary>
|
||||||
|
public readonly Sign Sign; |
||||||
|
|
||||||
|
public Comp(ComparisonKind kind, Sign sign, ILInstruction left, ILInstruction right) : base(OpCode.Comp, left, right) |
||||||
|
{ |
||||||
|
this.kind = kind; |
||||||
|
this.Sign = sign; |
||||||
|
this.inputType = ComputeInputType(left.ResultType, right.ResultType); |
||||||
|
} |
||||||
|
|
||||||
|
static StackType ComputeInputType(StackType left, StackType right) |
||||||
|
{ |
||||||
|
if (left == StackType.I || right == StackType.I) |
||||||
|
return StackType.I; |
||||||
|
Debug.Assert(left == right); |
||||||
|
return left; |
||||||
|
} |
||||||
|
|
||||||
|
public override void WriteTo(ITextOutput output) |
||||||
|
{ |
||||||
|
output.Write(OpCode); |
||||||
|
switch (Sign) { |
||||||
|
case Sign.Signed: |
||||||
|
output.Write(".signed"); |
||||||
|
break; |
||||||
|
case Sign.Unsigned: |
||||||
|
output.Write(".unsigned"); |
||||||
|
break; |
||||||
|
} |
||||||
|
output.Write('('); |
||||||
|
Left.WriteTo(output); |
||||||
|
output.Write(' '); |
||||||
|
output.Write(Kind.GetToken()); |
||||||
|
output.Write(' '); |
||||||
|
Right.WriteTo(output); |
||||||
|
output.Write(')'); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
Loading…
Reference in new issue