public override IExpression Rewrite(IConditional cond) { var newCond = new Conditional(cond); Switch.On(MutationTarget.PassInfo) .Case("to&&", () => { newCond.ResultIfTrue = cond.ResultIfFalse; newCond.ResultIfFalse = new CompileTimeConstant { Type = cond.ResultIfTrue.Type, Value = false, }; }) .Case("to||", () => { newCond.ResultIfFalse = cond.ResultIfTrue; newCond.ResultIfTrue = new CompileTimeConstant { Type = cond.ResultIfFalse.Type, Value = true, }; }).ThrowIfNoMatch(); return newCond; }
private static IExpression InvertConditional(Conditional conditional) { Contract.Requires(conditional != null); Contract.Ensures(Contract.Result<IExpression>() != null); var result = new Conditional() { Type = conditional.Type }; if (ExpressionHelper.IsIntegralZero(conditional.ResultIfTrue)) { result.Condition = conditional.Condition; result.ResultIfTrue = InvertCondition(conditional.ResultIfTrue); result.ResultIfFalse = InvertCondition(conditional.ResultIfFalse); } else { result.Condition = InvertCondition(conditional.Condition); result.ResultIfTrue = InvertCondition(conditional.ResultIfFalse); result.ResultIfFalse = InvertCondition(conditional.ResultIfTrue); } return result; }
internal static Conditional FixUpType(Conditional conditional) { Contract.Requires(conditional != null); conditional.Condition = ConvertToBoolean(conditional.Condition); var mergedType = conditional.ResultIfTrue.Type; if (!TypeHelper.TypesAreEquivalent(conditional.ResultIfTrue.Type, conditional.ResultIfFalse.Type)) { mergedType = TypeHelper.MergedType(TypeHelper.StackType(conditional.ResultIfTrue.Type), TypeHelper.StackType(conditional.ResultIfFalse.Type)); if (mergedType.TypeCode == PrimitiveTypeCode.Int32) { if (conditional.ResultIfTrue.Type.TypeCode == PrimitiveTypeCode.Boolean) { conditional.ResultIfFalse = ConvertToBoolean(conditional.ResultIfFalse); mergedType = conditional.ResultIfTrue.Type; } else if (conditional.ResultIfFalse.Type.TypeCode == PrimitiveTypeCode.Boolean) { conditional.ResultIfTrue = ConvertToBoolean(conditional.ResultIfTrue); mergedType = conditional.ResultIfFalse.Type; } } } conditional.Type = mergedType; return conditional; }
private bool ReplaceShortCircuitAnd4(BlockStatement b) { Contract.Requires(b != null); bool replacedPattern = false; var statements = b.Statements; for (int i = 0; i < statements.Count-2; i++) { var ifStatement1 = statements[i] as ConditionalStatement; if (ifStatement1 == null || !(ifStatement1.FalseBranch is EmptyStatement)) continue; var goto1 = ifStatement1.TrueBranch as GotoStatement; if (goto1 == null) continue; var labStat = statements[i+1] as LabeledStatement; if (labStat == null) continue; var gotos1 = this.gotosThatTarget[(uint)labStat.Label.UniqueKey]; if (gotos1 != null && gotos1.Count > 0) continue; var ifStatement2 = statements[i+2] as ConditionalStatement; if (ifStatement2 == null) continue; if (ifStatement2.TrueBranch is EmptyStatement) { var goto2 = ifStatement2.FalseBranch as GotoStatement; if (goto2 == null) continue; if (goto1.TargetStatement != goto2.TargetStatement) continue; var gotos = this.gotosThatTarget[(uint)goto1.TargetStatement.Label.UniqueKey]; if (gotos == null || gotos.Count == 0) continue; var falseConst = new CompileTimeConstant() { Value = false, Type = this.host.PlatformType.SystemBoolean }; var notCond1 = new LogicalNot() { Operand = ifStatement1.Condition, Type = this.host.PlatformType.SystemBoolean }; var conditional = new Conditional() { Condition = notCond1, ResultIfTrue = ifStatement2.Condition, ResultIfFalse = falseConst, Type = this.host.PlatformType.SystemBoolean }; ifStatement2.Condition = conditional; statements.RemoveRange(i, 2); gotos.Remove(goto1); replacedPattern = true; } else if (ifStatement2.FalseBranch is EmptyStatement) { var goto2 = ifStatement2.TrueBranch as GotoStatement; if (goto2 == null) continue; if (goto1.TargetStatement != goto2.TargetStatement) continue; var gotos = this.gotosThatTarget[(uint)goto1.TargetStatement.Label.UniqueKey]; if (gotos == null || gotos.Count == 0) continue; var trueConst = new CompileTimeConstant() { Value = true, Type = this.host.PlatformType.SystemBoolean }; var cond1 = ifStatement1.Condition; var conditional = new Conditional() { Condition = cond1, ResultIfTrue = trueConst, ResultIfFalse = ifStatement2.Condition, Type = this.host.PlatformType.SystemBoolean }; ifStatement2.Condition = conditional; statements.RemoveRange(i, 2); gotos.Remove(goto1); replacedPattern = true; } } return replacedPattern; }
private bool ReplaceShortCircuitAnd2(BlockStatement b) { Contract.Requires(b != null); bool replacedPattern = false; var statements = b.Statements; for (int i = 0; i < statements.Count-3; i++) { var ifStatement = statements[i] as ConditionalStatement; if (ifStatement == null) continue; var gotoFalseCase = ifStatement.FalseBranch as GotoStatement; if (gotoFalseCase == null) continue; Contract.Assume(ifStatement.TrueBranch is EmptyStatement); var labeledStatement = statements[i+1] as LabeledStatement; if (labeledStatement == null) continue; var gotos = this.gotosThatTarget[(uint)labeledStatement.Label.UniqueKey]; if (gotos != null && gotos.Count > 0) continue; var ifStatement2 = statements[i+2] as ConditionalStatement; if (ifStatement2 == null) continue; var gotoTrueCase = ifStatement2.TrueBranch as GotoStatement; if (gotoTrueCase == null) continue; Contract.Assume(ifStatement2.FalseBranch is EmptyStatement); var labeledStatement2 = statements[i+3] as LabeledStatement; if (labeledStatement2 == null) continue; if (labeledStatement2 == gotoFalseCase.TargetStatement) { gotos = this.gotosThatTarget[(uint)labeledStatement2.Label.UniqueKey]; Contract.Assume(gotos != null && gotos.Count > 0); if (gotos.Count > 1) continue; var falseConst = new CompileTimeConstant() { Value = false, Type = this.host.PlatformType.SystemBoolean }; var conditional = new Conditional() { Condition = ifStatement.Condition, ResultIfTrue = ifStatement2.Condition, ResultIfFalse = falseConst, Type = this.host.PlatformType.SystemBoolean }; ifStatement2.Condition = conditional; statements.RemoveRange(i, 2); gotos.Remove(gotoFalseCase); replacedPattern = true; } else { if (gotoFalseCase.TargetStatement != gotoTrueCase.TargetStatement) continue; //actually have a short circuit or here gotos = this.gotosThatTarget[(uint)gotoFalseCase.TargetStatement.Label.UniqueKey]; Contract.Assume(gotos != null && gotos.Count > 0); var trueConst = new CompileTimeConstant() { Value = true, Type = this.host.PlatformType.SystemBoolean }; var invertedCond = new LogicalNot() { Operand = ifStatement.Condition, Type = this.host.PlatformType.SystemBoolean }; var conditional = new Conditional() { Condition = invertedCond, ResultIfTrue = trueConst, ResultIfFalse = ifStatement2.Condition, Type = this.host.PlatformType.SystemBoolean }; ifStatement2.Condition = conditional; statements.RemoveRange(i, 2); gotos.Remove(gotoFalseCase); replacedPattern = true; } } return replacedPattern; }
private bool ReplaceShortCircuitAnd(BlockStatement b) { Contract.Requires(b != null); bool replacedPattern = false; var statements = b.Statements; for (int i = 0; i < statements.Count-6; i++) { var ifStatement = statements[i] as ConditionalStatement; if (ifStatement == null) continue; var gotoFalseCase = ifStatement.FalseBranch as GotoStatement; if (gotoFalseCase == null) continue; Contract.Assume(ifStatement.TrueBranch is EmptyStatement); var labeledStatement = statements[i+1] as LabeledStatement; if (labeledStatement == null) continue; var gotos = this.gotosThatTarget[(uint)labeledStatement.Label.UniqueKey]; if (gotos != null && gotos.Count > 0) continue; var pushTrueCase = statements[i+2] as PushStatement; if (pushTrueCase == null) continue; if (pushTrueCase.ValueToPush.Type.TypeCode != PrimitiveTypeCode.Boolean) continue; var gotoEnd = statements[i+3] as GotoStatement; if (gotoEnd == null) continue; var labeledStatement2 = statements[i+4] as LabeledStatement; if (labeledStatement2 == null || labeledStatement2 != gotoFalseCase.TargetStatement) continue; gotos = this.gotosThatTarget[(uint)labeledStatement2.Label.UniqueKey]; Contract.Assume(gotos != null && gotos.Count > 0); if (gotos.Count > 1) continue; var pushFalseCase = statements[i+5] as PushStatement; if (pushFalseCase == null) continue; var falseCaseVal = pushFalseCase.ValueToPush as CompileTimeConstant; if (falseCaseVal == null || !(falseCaseVal.Value is int)) continue; var endLabel = statements[i+6] as LabeledStatement; if (endLabel == null || gotoEnd.TargetStatement != endLabel) continue; Conditional conditional; if (((int)falseCaseVal.Value) != 0) { var trueConst = new CompileTimeConstant() { Value = true, Type = this.host.PlatformType.SystemBoolean }; var cond = new LogicalNot() { Operand = ifStatement.Condition, Type = this.host.PlatformType.SystemBoolean }; conditional = new Conditional() { Condition = cond, ResultIfTrue = trueConst, ResultIfFalse = pushTrueCase.ValueToPush, Type = this.host.PlatformType.SystemBoolean }; } else { var falseConst = new CompileTimeConstant() { Value = false, Type = this.host.PlatformType.SystemBoolean }; conditional = new Conditional() { Condition = ifStatement.Condition, ResultIfTrue = pushTrueCase.ValueToPush, ResultIfFalse = falseConst, Type = this.host.PlatformType.SystemBoolean }; } pushFalseCase.ValueToPush = conditional; statements.RemoveAt(i+6); statements.RemoveRange(i, 5); replacedPattern = true; } return replacedPattern; }
private bool ReplaceConditionalExpressionPattern(BlockStatement b) { Contract.Requires(b != null); bool replacedPattern = false; var statements = b.Statements; for (int i = 0; i < statements.Count-6; i++) { var ifStatement = statements[i] as ConditionalStatement; if (ifStatement == null) continue; var gotoTrueCase = ifStatement.TrueBranch as GotoStatement; if (gotoTrueCase == null) continue; Contract.Assume(ifStatement.FalseBranch is EmptyStatement); var labeledStatement = statements[i+1] as LabeledStatement; if (labeledStatement == null) continue; var gotos = this.gotosThatTarget[(uint)labeledStatement.Label.UniqueKey]; if (gotos != null && gotos.Count > 0) continue; var pushFalseCase = statements[i+2] as PushStatement; if (pushFalseCase == null) continue; var gotoEnd = statements[i+3] as GotoStatement; if (gotoEnd == null) continue; var labeledStatement2 = statements[i+4] as LabeledStatement; if (labeledStatement2 == null || labeledStatement2 != gotoTrueCase.TargetStatement) continue; gotos = this.gotosThatTarget[(uint)labeledStatement2.Label.UniqueKey]; Contract.Assume(gotos != null && gotos.Count > 0); if (gotos.Count > 1) continue; var pushTrueCase = statements[i+5] as PushStatement; if (pushTrueCase == null) continue; var endLabel = statements[i+6] as LabeledStatement; if (endLabel == null || gotoEnd.TargetStatement != endLabel) continue; var conditional = new Conditional() { Condition = ifStatement.Condition, ResultIfTrue = pushTrueCase.ValueToPush, ResultIfFalse = pushFalseCase.ValueToPush }; pushTrueCase.ValueToPush = TypeInferencer.FixUpType(conditional); pushTrueCase.Locations.AddRange(ifStatement.Locations); gotos = this.gotosThatTarget[(uint)endLabel.Label.UniqueKey]; Contract.Assume(gotos != null && gotos.Count > 0); gotos.Remove(gotoEnd); if (gotos.Count == 0) statements.RemoveAt(i+6); statements.RemoveRange(i, 5); replacedPattern = true; } return replacedPattern; }
/// <summary> /// Visits the specified conditional. /// </summary> /// <param name="conditional">The conditional.</param> public override void Visit(IConditional conditional) { Conditional mutableConditional = conditional as Conditional; if (alwaysMakeACopy || mutableConditional == null) mutableConditional = new Conditional(conditional); this.resultExpression = this.myCodeMutator.Visit(mutableConditional); }
/// <summary> /// Finds the following pattern: /// i : c ? A : B; // either A or B must be an empty statement and the other is "goto L1;" /// i+1 : push x; /// i+2 : goto L2; /// i+3 : Block1 /// 0 : L1; /// 1 : push y; /// 2 : goto L2; /// 3 : Block2 /// 0 : whatever (but presumably it is the label L2) /// /// Transforms it into: /// i : push d ? X : Y; /// i+1 : goto L1; /// i+2 : Block 2 /// /// Where if A is the empty statement, /// d == c, X == x, Y == y /// If B is the empty statement and y is zero /// d == !c, X == x, Y == y /// If B is the empty statement and y is not zero /// d == c, X == y, Y == x /// And Block1 is deleted from the list. /// </summary> private bool ReplaceShortCircuitPatternCreatedByCCI2(List<IStatement> statements, int i) { if (i > statements.Count - 4) return false; ConditionalStatement/*?*/ conditionalStatement = statements[i] as ConditionalStatement; if (conditionalStatement == null) return false; PushStatement/*?*/ push1 = statements[i + 1] as PushStatement; if (push1 == null) return false; GotoStatement/*?*/ Goto = statements[i + 2] as GotoStatement; if (Goto == null) return false; BasicBlock/*?*/ block1 = statements[i + 3] as BasicBlock; if (block1 == null) return false; if (block1.Statements.Count < 4) return false; LabeledStatement/*?*/ label = block1.Statements[0] as LabeledStatement; if (label == null) return false; List<IGotoStatement> branchesToThisLabel; if (this.predecessors.TryGetValue(label, out branchesToThisLabel)) { if (1 < branchesToThisLabel.Count) return false; } // TODO? Should we make sure that one of the branches in the conditionalStatement is // to label? PushStatement/*?*/ push2 = block1.Statements[1] as PushStatement; if (push2 == null) return false; GotoStatement/*?*/ Goto2 = block1.Statements[2] as GotoStatement; if (Goto2 == null) return false; if (Goto.TargetStatement != Goto2.TargetStatement) return false; BasicBlock/*?*/ block2 = block1.Statements[3] as BasicBlock; if (block2 == null) return false; if (conditionalStatement.TrueBranch is EmptyStatement) { Conditional conditional = new Conditional(); conditional.Condition = conditionalStatement.Condition; conditional.ResultIfTrue = push1.ValueToPush; conditional.ResultIfFalse = push2.ValueToPush; conditional.Type = TypeHelper.MergedType(TypeHelper.StackType(conditional.ResultIfTrue.Type), TypeHelper.StackType(conditional.ResultIfFalse.Type)); push1.ValueToPush = conditional; push1.Locations = conditionalStatement.Locations; statements[i] = push1; statements[i + 1] = statements[i + 2]; // move the goto up statements[i + 2] = block2; statements.RemoveRange(i + 3, 1); return true; } if (conditionalStatement.FalseBranch is EmptyStatement) { Conditional conditional = new Conditional(); if (ExpressionHelper.IsIntegralZero(push2.ValueToPush)) { conditional.Condition = InvertCondition(conditionalStatement.Condition); conditional.ResultIfTrue = push1.ValueToPush; conditional.ResultIfFalse = push2.ValueToPush; } else { conditional.Condition = conditionalStatement.Condition; conditional.ResultIfTrue = push2.ValueToPush; conditional.ResultIfFalse = push1.ValueToPush; } conditional.Locations = conditionalStatement.Locations; conditional.Type = TypeHelper.MergedType(TypeHelper.StackType(conditional.ResultIfTrue.Type), TypeHelper.StackType(conditional.ResultIfFalse.Type)); push1.ValueToPush = conditional; push1.Locations = conditionalStatement.Locations; statements[i] = push1; statements[i + 1] = statements[i + 2]; // move the goto up statements[i + 2] = block2; statements.RemoveRange(i + 3, 1); return true; } return false; }
private bool ReplaceShortCircuitPattern3(List<IStatement> statements, int i) { if (i > statements.Count - 3) return false; ConditionalStatement/*?*/ conditionalStatement = statements[i] as ConditionalStatement; if (conditionalStatement == null) return false; ConditionalStatement/*?*/ conditionalStatement2 = statements[i+1] as ConditionalStatement; if (conditionalStatement2 == null) return false; if (statements[i+2] is ConditionalStatement) { if (!this.ReplaceShortCircuitPattern2(statements, i+1)) return false; if (i > statements.Count - 3) return false; conditionalStatement2 = statements[i+1] as ConditionalStatement; if (conditionalStatement2 == null) return false; } GotoStatement/*?*/ gotoStatement = conditionalStatement.FalseBranch as GotoStatement; if (gotoStatement == null) return false; if (!(conditionalStatement.TrueBranch is EmptyStatement)) return false; GotoStatement/*?*/ gotoStatement2 = conditionalStatement2.FalseBranch as GotoStatement; if (gotoStatement2 == null) { gotoStatement2 = conditionalStatement2.TrueBranch as GotoStatement; if (gotoStatement2 == null) return false; if (!(conditionalStatement2.FalseBranch is EmptyStatement)) return false; //brfalse, brtrue, ... could be A && B || C BasicBlock/*?*/ bb = statements[i+2] as BasicBlock; if (bb == null) return false; if (bb.Statements.Count < 1 || !(bb.Statements[0] == gotoStatement.TargetStatement)) return false; //we have: //i+0: if (cond1) {} else goto lab1; //i+1: if (cond2) goto lab2; //i+2: {....} Conditional conditional = new Conditional(); conditional.Condition = conditionalStatement.Condition; conditional.Locations = conditionalStatement.Locations; conditional.ResultIfTrue = conditionalStatement2.Condition; conditional.ResultIfFalse = new CompileTimeConstant() { Value = 0, Type = this.sourceMethodBody.MethodDefinition.Type.PlatformType.SystemInt32 }; conditional.Type = TypeHelper.MergedType(TypeHelper.StackType(conditional.ResultIfTrue.Type), TypeHelper.StackType(conditional.ResultIfFalse.Type)); conditionalStatement2.Condition = conditional; statements.RemoveAt(i); //we now have: //i+0: if (cond1 ? cond2 : 0) goto lab2; //i+1: {....} //which amounts to: // if (cond1 && cond2) goto lab2; // {...} return this.ReplaceShortCircuitPattern2(statements, i); } if (!(conditionalStatement2.TrueBranch is EmptyStatement)) return false; if (gotoStatement.TargetStatement == gotoStatement2.TargetStatement) { Conditional conditional = new Conditional(); conditional.Condition = conditionalStatement.Condition; conditional.Locations = conditionalStatement.Locations; conditional.ResultIfTrue = conditionalStatement2.Condition; conditional.ResultIfFalse = new CompileTimeConstant() { Value = 0, Type = this.sourceMethodBody.MethodDefinition.Type.PlatformType.SystemInt32 }; conditional.Type = TypeHelper.MergedType(TypeHelper.StackType(conditional.ResultIfTrue.Type), TypeHelper.StackType(conditional.ResultIfFalse.Type)); conditionalStatement2.Condition = conditional; statements.RemoveAt(i); return true; } return false; }
private bool ReplaceShortCircuitPattern2(List<IStatement> statements, int i) { if (i > statements.Count - 3) return false; ConditionalStatement/*?*/ conditionalStatement = statements[i] as ConditionalStatement; if (conditionalStatement == null) return false; ConditionalStatement/*?*/ conditionalStatement2 = statements[i+1] as ConditionalStatement; if (conditionalStatement2 == null) return false; if (statements[i+2] is ConditionalStatement) { if (!ReplaceShortCircuitPattern2(statements, i+1)) return false; if (i > statements.Count - 3) return false; conditionalStatement2 = statements[i+1] as ConditionalStatement; if (conditionalStatement2 == null) return false; } BasicBlock/*?*/ block = statements[i+2] as BasicBlock; if (block == null) { return this.ReplaceShortCircuitPattern3(statements, i); } if (block.Statements.Count < 1) return false; GotoStatement/*?*/ gotoStatement = conditionalStatement.TrueBranch as GotoStatement; if (gotoStatement == null) { return this.ReplaceShortCircuitPattern3(statements, i); } if (!(conditionalStatement.FalseBranch is EmptyStatement)) return false; if (gotoStatement.TargetStatement != block.Statements[0]) return false; if (!(conditionalStatement2.TrueBranch is EmptyStatement)) { if (!(conditionalStatement2.TrueBranch is GotoStatement)) return false; if (!(conditionalStatement2.FalseBranch is EmptyStatement)) return false; //Now have: //if (cond1) goto lab1; //if (cond2) goto lab2; //lab1:... conditionalStatement2.Condition = InvertCondition(conditionalStatement2.Condition); IStatement temp = conditionalStatement2.TrueBranch; conditionalStatement2.TrueBranch = conditionalStatement2.FalseBranch; conditionalStatement2.FalseBranch = temp; //Now have: //if (cond1) goto lab1; //if (!cond2) {} else goto lab2; //lab1:... } else { if (!(conditionalStatement2.FalseBranch is GotoStatement)) return false; } //Now have: //if (cond1) goto lab1; //if (cond2a) {} else goto lab2; //lab1:... Conditional conditional = new Conditional(); conditional.Condition = conditionalStatement.Condition; conditional.Locations = conditionalStatement.Locations; conditional.ResultIfTrue = new CompileTimeConstant() { Value = 1, Type = this.sourceMethodBody.MethodDefinition.Type.PlatformType.SystemInt32 }; conditional.ResultIfFalse = conditionalStatement2.Condition; conditional.Type = TypeHelper.MergedType(TypeHelper.StackType(conditional.ResultIfTrue.Type), TypeHelper.StackType(conditional.ResultIfFalse.Type)); conditionalStatement2.Condition = conditional; statements.RemoveAt(i); //Now have: //if (cond1 ? true : cond2a) {} goto lab2; //lab1:.... // //Which amounts to //if (!(cond1 || cond2a)) goto lab2; //lab1:... return true; }
/// <summary> /// Finds the following pattern: /// i : if (c) A else B; // either A or B must be an empty statement and the other is "goto L1;" /// i+1 : push x; /// i+2 : goto L2; /// i+3 : Block1 /// 0 : L1; /// 1 : push y; /// 2 : Block2 /// 0 : L2; /// 1 : (rest of statements in Block2) /// /// Transforms it into: /// i : push (d ? X : Y); /// i+1 : (rest of statements in Block2, preceded by L2 if there are more branches to L2 than just the one that was at i+2) /// /// Where if A is the empty statement, then /// d == c, X == x, Y == y /// If B is the empty statement, then if y is zero, /// d == !c, X == x, Y == y /// If B is the empty statement, then if y is not zero, /// d == c, X == y, Y == x /// </summary> private bool ReplaceShortCircuitPattern(List<IStatement> statements, int i) { if (i > statements.Count - 4) return false; ConditionalStatement/*?*/ conditionalStatement = statements[i] as ConditionalStatement; if (conditionalStatement == null) return false; if (statements[i+1] is ConditionalStatement) return this.ReplaceChainedShortCircuitBooleanPattern(statements, i); GotoStatement/*?*/ gotoL1 = null; if (conditionalStatement.TrueBranch is EmptyStatement) gotoL1 = conditionalStatement.FalseBranch as GotoStatement; else if (conditionalStatement.FalseBranch is EmptyStatement) gotoL1 = conditionalStatement.TrueBranch as GotoStatement; if (gotoL1 == null) return false; PushStatement/*?*/ push = statements[i+1] as PushStatement; if (push == null) return false; GotoStatement/*?*/ gotoL2 = statements[i+2] as GotoStatement; if (gotoL2 == null) return false; BasicBlock/*?*/ block = statements[i+3] as BasicBlock; if (block == null) return false; if (block.Statements.Count < 3) return false; LabeledStatement/*?*/ l1 = block.Statements[0] as LabeledStatement; if (l1 == null) return false; if (l1 != gotoL1.TargetStatement) return false; List<IGotoStatement> branchesToThisLabel; if (this.predecessors.TryGetValue(l1, out branchesToThisLabel)) { if (branchesToThisLabel.Count > 1) return false; } PushStatement/*?*/ push2 = block.Statements[1] as PushStatement; if (push2 == null) return false; BasicBlock/*?*/ block2 = block.Statements[2] as BasicBlock; if (block2 == null || block2.Statements.Count < 1 || block2.Statements[0] != gotoL2.TargetStatement) return false; Conditional conditional = new Conditional(); if (conditionalStatement.TrueBranch is EmptyStatement) { conditional.Condition = conditionalStatement.Condition; conditional.ResultIfTrue = push.ValueToPush; conditional.ResultIfFalse = push2.ValueToPush; } else if (conditionalStatement.FalseBranch is EmptyStatement) { if (ExpressionHelper.IsIntegralZero(push2.ValueToPush)) { conditional.Condition = InvertCondition(conditionalStatement.Condition); conditional.ResultIfTrue = push.ValueToPush; conditional.ResultIfFalse = push2.ValueToPush; } else { conditional.Condition = conditionalStatement.Condition; conditional.ResultIfTrue = push2.ValueToPush; conditional.ResultIfFalse = push.ValueToPush; } } conditional.Type = TypeHelper.MergedType(TypeHelper.StackType(conditional.ResultIfTrue.Type), TypeHelper.StackType(conditional.ResultIfFalse.Type)); conditional.Locations = conditionalStatement.Locations; push.ValueToPush = conditional; push.Locations = conditional.Locations; statements[i] = push; statements.RemoveRange(i+1, 3); var l2 = gotoL2.TargetStatement; this.predecessors.TryGetValue(l2, out branchesToThisLabel); branchesToThisLabel.Remove(gotoL2); if (branchesToThisLabel.Count == 0) block2.Statements.RemoveAt(0); statements.InsertRange(i+1, block2.Statements); return true; }
/// <summary> /// Rewrites the children of the given conditional expression. /// </summary> public virtual void RewriteChildren(Conditional conditional) { this.RewriteChildren((Expression)conditional); conditional.Condition = this.Rewrite(conditional.Condition); conditional.ResultIfTrue = this.Rewrite(conditional.ResultIfTrue); conditional.ResultIfFalse = this.Rewrite(conditional.ResultIfFalse); }
/// <summary> /// Visits the specified conditional. /// </summary> /// <param name="conditional">The conditional.</param> public override void Visit(IConditional conditional) { Conditional mutableConditional = new Conditional(conditional); this.resultExpression = this.myCodeCopier.DeepCopy(mutableConditional); }
private bool ReplaceShortCircuitAnd6(BlockStatement b) { Contract.Requires(b != null); bool replacedPattern = false; var statements = b.Statements; for (int i = 0; i < statements.Count-8; i++) { var ifStatement = statements[i] as ConditionalStatement; if (ifStatement == null) continue; var gotoFalseCase = ifStatement.FalseBranch as GotoStatement; if (gotoFalseCase == null) continue; Contract.Assume(ifStatement.TrueBranch is EmptyStatement); var labeledStatement = statements[i+1] as LabeledStatement; if (labeledStatement == null) continue; var gotos = this.gotosThatTarget[(uint)labeledStatement.Label.UniqueKey]; if (gotos != null && gotos.Count > 0) continue; var ifStatement2 = statements[i+2] as ConditionalStatement; if (ifStatement2 == null) continue; var gotoTrueCase = ifStatement2.FalseBranch as GotoStatement; if (gotoTrueCase == null) continue; if (!(ifStatement2.TrueBranch is EmptyStatement)) continue; var labeledStatement2 = statements[i+3] as LabeledStatement; if (labeledStatement2 == null || labeledStatement2 != gotoFalseCase.TargetStatement) continue; gotos = this.gotosThatTarget[(uint)labeledStatement2.Label.UniqueKey]; Contract.Assume(gotos != null && gotos.Count > 0); if (gotos.Count > 1) continue; Contract.Assume(gotos[0] == gotoFalseCase); var pushFalseCase = statements[i+4] as PushStatement; if (pushFalseCase == null) continue; if (pushFalseCase.ValueToPush.Type.TypeCode != PrimitiveTypeCode.Boolean) continue; var gotoEnd = statements[i+5] as GotoStatement; if (gotoEnd == null) continue; var labeledStatement3 = statements[i+6] as LabeledStatement; if (labeledStatement3 == null || labeledStatement3 != gotoTrueCase.TargetStatement) continue; gotos = this.gotosThatTarget[(uint)labeledStatement3.Label.UniqueKey]; Contract.Assume(gotos != null && gotos.Count > 0); if (gotos.Count > 1) continue; Contract.Assume(gotos[0] == gotoTrueCase); var pushTrueCase = statements[i+7] as PushStatement; if (pushTrueCase == null) continue; if (pushTrueCase.ValueToPush.Type.TypeCode != PrimitiveTypeCode.Int32) continue; var pushTrueVal = pushTrueCase.ValueToPush as CompileTimeConstant; if (pushTrueVal == null || !(pushTrueVal.Value is int)) continue; if (1 != (int)pushTrueVal.Value) continue; var endLabel = statements[i+8] as LabeledStatement; if (endLabel == null || gotoEnd.TargetStatement != endLabel) continue; gotos = this.gotosThatTarget[(uint)endLabel.Label.UniqueKey]; Contract.Assume(gotos != null && gotos.Count > 0); if (gotos.Count > 1) continue; Contract.Assume(gotos[0] == gotoEnd); var falseConst = new CompileTimeConstant() { Value = false, Type = this.host.PlatformType.SystemBoolean }; var invertedCond1 = IfThenElseReplacer.InvertCondition(ifStatement2.Condition); var conditional1 = new Conditional() { Condition = ifStatement.Condition, ResultIfTrue = invertedCond1, ResultIfFalse = falseConst, Type = this.host.PlatformType.SystemBoolean }; var trueConst = new CompileTimeConstant() { Value = true, Type = this.host.PlatformType.SystemBoolean }; var invertedCond2 = IfThenElseReplacer.InvertCondition(pushFalseCase.ValueToPush); var conditional2 = new Conditional() { Condition = conditional1, ResultIfTrue = trueConst, ResultIfFalse = invertedCond2, Type = this.host.PlatformType.SystemBoolean }; pushTrueCase.ValueToPush = conditional2; statements.RemoveAt(i+8); statements.RemoveRange(i, 7); replacedPattern = true; } return replacedPattern; }
/// <summary> /// Visits the specified conditional. /// </summary> /// <param name="conditional">The conditional.</param> /// <returns></returns> protected virtual IExpression DeepCopy(Conditional conditional) { conditional.Condition = Substitute(conditional.Condition); conditional.ResultIfTrue = Substitute(conditional.ResultIfTrue); conditional.ResultIfFalse = Substitute(conditional.ResultIfFalse); conditional.Type = this.Substitute(conditional.Type); return conditional; }
/// <summary> /// Visits the specified conditional. /// </summary> /// <param name="conditional">The conditional.</param> /// <returns></returns> public virtual IExpression Visit(Conditional conditional) { conditional.Condition = Visit(conditional.Condition); conditional.ResultIfTrue = Visit(conditional.ResultIfTrue); conditional.ResultIfFalse = Visit(conditional.ResultIfFalse); conditional.Type = this.Visit(conditional.Type); return conditional; }