private ConditionLogicalConstruct CreateComplexCondition(ConditionLogicalConstruct conditionNode) { V_0 = conditionNode.get_ConditionExpression(); V_1 = new HashSet <ILogicalConstruct>(); V_2 = conditionNode; dummyVar0 = V_1.Add(V_2); V_3 = V_2.get_TrueSuccessor(); V_4 = V_2.get_FalseSuccessor(); while (true) { if (!this.CanBePartOfComplexCondition(V_3, V_1, V_2.get_FalseCFGSuccessor())) { if (!this.CanBePartOfComplexCondition(V_4, V_1, V_2.get_TrueCFGSuccessor())) { break; } V_6 = V_4 as ConditionLogicalConstruct; if (V_6.get_TrueSuccessor() != V_3) { V_6.Negate(this.typeSystem); } V_8 = 11; } else { V_6 = V_3 as ConditionLogicalConstruct; if (V_6.get_FalseSuccessor() != V_4) { V_6.Negate(this.typeSystem); } V_8 = 12; } V_0 = new BinaryExpression(V_8, V_0, V_6.get_ConditionExpression(), this.typeSystem, null, false); V_0.set_ExpressionType(this.booleanTypeReference); V_2 = V_6; V_3 = V_2.get_TrueSuccessor(); V_4 = V_2.get_FalseSuccessor(); dummyVar1 = V_1.Add(V_2); } if (V_1.get_Count() == 1) { return(conditionNode); } V_5 = new HashSet <ConditionLogicalConstruct>(); V_9 = V_1.GetEnumerator(); try { while (V_9.MoveNext()) { V_10 = (ConditionLogicalConstruct)V_9.get_Current(); dummyVar2 = V_5.Add(V_10); } } finally { ((IDisposable)V_9).Dispose(); } return(new ConditionLogicalConstruct(conditionNode, V_2, V_5, V_0)); }
private IfLogicalConstruct(ConditionLogicalConstruct condition, BlockLogicalConstruct thenBlock, BlockLogicalConstruct elseBlock) { condition.LogicalContainer = this; this.Condition = condition; this.Then = thenBlock; this.Else = elseBlock; RedirectChildrenToNewParent(GetIfBody()); }
private IfLogicalConstruct(ConditionLogicalConstruct condition, BlockLogicalConstruct thenBlock, BlockLogicalConstruct elseBlock) { condition.LogicalContainer = this; this.Condition = condition; this.Then = thenBlock; this.Else = elseBlock; RedirectChildrenToNewParent(GetIfBody()); }
private IfLogicalConstruct(ConditionLogicalConstruct condition, BlockLogicalConstruct thenBlock, BlockLogicalConstruct elseBlock) { base(); condition.set_LogicalContainer(this); this.set_Condition(condition); this.set_Then(thenBlock); this.set_Else(elseBlock); this.RedirectChildrenToNewParent(this.GetIfBody()); return; }
public ConditionLogicalConstruct(ConditionLogicalConstruct entry, ConditionLogicalConstruct lastNode, HashSet <ConditionLogicalConstruct> body, Expression conditionExpression) { base(); this.set_Entry(entry.get_FirstBlock()); this.set_TrueCFGSuccessor(lastNode.get_TrueCFGSuccessor()); this.set_FalseCFGSuccessor(lastNode.get_FalseCFGSuccessor()); this.set_ConditionExpression(conditionExpression); this.RedirectChildrenToNewParent(this.RestoreOriginalCFGNodes(body)); this.AddTrueFalseSuccessors(); this.set_LogicalContainer(null); return; }
/// <summary> /// Traverses the graph and tries to merge conditions into complex condition constructs. /// </summary> /// <param name="theConstruct"></param> /// <returns>Returns true if there was a successful merge.</returns> private bool TryTraverseAndMerge(ILogicalConstruct theConstruct) { //The algorithm is split into iterations, because once it merges a complex condition this condition can be used with one of //its predecessors to create another complex condition. This means that special modifications are needed to the traversal, //which may lead to bugs and is overall more hard to maintain. //We use BFS to traverse the subgraph HashSet <ILogicalConstruct> traversedNodes = new HashSet <ILogicalConstruct>(); Queue <ILogicalConstruct> traverseQueue = new Queue <ILogicalConstruct>(); traverseQueue.Enqueue(theConstruct.Entry as ILogicalConstruct); bool changed = false; while (traverseQueue.Count > 0) { ILogicalConstruct currentNode = traverseQueue.Dequeue(); //For each node that is a condition construct we try to create a complex condition starting from it ConditionLogicalConstruct currentConditionNode = currentNode as ConditionLogicalConstruct; if (currentConditionNode != null) { ConditionLogicalConstruct newNode = CreateComplexCondition(currentConditionNode); //If we succeed we mark that there was a change in the subgraph; changed |= newNode != currentNode; //We change the currentNode to the newNode since if there was a merge then the currentNode will be a successor of the newNode currentNode = newNode; } //We mark the current node as traversed traversedNodes.Add(currentNode); //Normal bfs continues foreach (ILogicalConstruct successor in currentNode.SameParentSuccessors) { if (!traversedNodes.Contains(successor)) { traverseQueue.Enqueue(successor); } } while (traverseQueue.Count > 0 && traversedNodes.Contains(traverseQueue.Peek())) { traverseQueue.Dequeue(); } } return(changed); }
public ConditionLogicalConstruct(ConditionLogicalConstruct entry, ConditionLogicalConstruct lastNode, HashSet <ConditionLogicalConstruct> body, Expression conditionExpression) { Entry = entry.FirstBlock; TrueCFGSuccessor = lastNode.TrueCFGSuccessor; FalseCFGSuccessor = lastNode.FalseCFGSuccessor; ConditionExpression = conditionExpression; RedirectChildrenToNewParent(RestoreOriginalCFGNodes(body)); AddTrueFalseSuccessors(); LogicalContainer = null; }
/// <summary> /// Gets the candidates to become conditions of if constructs in postorder. /// </summary> /// <param name="construct"></param> /// <returns></returns> private IEnumerable <ConditionLogicalConstruct> GetPostOrderedIfConditionCandidates(DFSTree dfsTree) { //The post order is so that we start making the if constructs from the innermost nested first (if there is nesting). for (int i = dfsTree.ReversePostOrder.Count - 1; i >= 0; i--) { ConditionLogicalConstruct currentConstruct = dfsTree.ReversePostOrder[i].Construct as ConditionLogicalConstruct; //For candidates we take these conditions that have 2 same parent successors. //TODO: consider taking the conditions with 1 same parent successor. if (currentConstruct != null && currentConstruct.SameParentSuccessors.Count == 2) { yield return(currentConstruct); } } }
public ConditionLogicalConstruct(ConditionLogicalConstruct entry, ConditionLogicalConstruct lastNode, HashSet<ConditionLogicalConstruct> body, Expression conditionExpression) { Entry = entry.FirstBlock; TrueCFGSuccessor = lastNode.TrueCFGSuccessor; FalseCFGSuccessor = lastNode.FalseCFGSuccessor; ConditionExpression = conditionExpression; RedirectChildrenToNewParent(RestoreOriginalCFGNodes(body)); AddTrueFalseSuccessors(); LogicalContainer = null; }
/// <summary> /// Creates simple conditions containing only one CFG construct (may be partial). /// </summary> private void CreateSimpleConditions() { //Since we've split the CFG constructs in the CFGBlockSplitter, we now know that if an instruction block is a condition block, //the last of the (partial) CFG constructs holds the condition expression. //The only thing left to check is if the block is not a switch block, since switch blocks are a special case and are not proccessed as //normal conditions. foreach (CFGBlockLogicalConstruct[] cfgConstructsArray in logicalBuilderContext.CFGBlockToLogicalConstructMap.Values) { CFGBlockLogicalConstruct cfgConstruct = cfgConstructsArray[cfgConstructsArray.Length - 1]; InstructionBlock theInstructionBlock = cfgConstruct.TheBlock; if (theInstructionBlock.Successors.Length == 2 && theInstructionBlock.Successors[0] != theInstructionBlock.Successors[1] && theInstructionBlock.Last.OpCode.Code != Code.Switch) { ConditionLogicalConstruct.GroupInSimpleConditionConstruct(cfgConstruct); } } }
/// <summary> /// Creates a new loop construct and attaches it to the logical tree. /// </summary> /// <param name="entry">The entry to the loop construct.</param> /// <param name="loopBody">Collection containing all of the constructs in the loop body.</param> /// <param name="loopType">The type of the loop.</param> /// <param name="loopCondition">The condition of the loop.</param> public LoopLogicalConstruct(ILogicalConstruct entry, HashSet<ILogicalConstruct> loopBody, LoopType loopType, ConditionLogicalConstruct loopCondition, TypeSystem typeSystem) { if (loopCondition != null) { loopCondition.LogicalContainer = this; } LoopType = loopType; LoopCondition = loopCondition; if(this.LoopType != LoopType.InfiniteLoop) { loopBody.Remove(LoopCondition); } DetermineLoopBodyBlock(entry, loopBody); RedirectChildrenToNewParent(GetLoopChildrenCollection()); FixLoopCondition(typeSystem); }
private void CreateSimpleConditions() { V_0 = this.logicalBuilderContext.get_CFGBlockToLogicalConstructMap().get_Values().GetEnumerator(); try { while (V_0.MoveNext()) { stackVariable8 = V_0.get_Current(); V_1 = stackVariable8[(int)stackVariable8.Length - 1]; V_2 = V_1.get_TheBlock(); if ((int)V_2.get_Successors().Length != 2 || !InstructionBlock.op_Inequality(V_2.get_Successors()[0], V_2.get_Successors()[1]) || V_2.get_Last().get_OpCode().get_Code() == 68) { continue; } dummyVar0 = ConditionLogicalConstruct.GroupInSimpleConditionConstruct(V_1); } } finally { ((IDisposable)V_0).Dispose(); } return; }
/// <summary> /// Tries to build an if construct with condition - the specified condition. /// </summary> /// <remarks> /// The idea is to get the dominated nodes of the true successor to create the then block and the dominated nodes of the false successor /// to create the else block. /// If both the then and else blocks have successors, then they must have a common successor to create the if construct. /// </remarks> /// <param name="condition"></param> /// <returns>True on success.</returns> private bool TryBuildIfConstruct(ConditionLogicalConstruct condition, DominatorTree dominatorTree, DFSTree dfsTree) { //Store the true and false successors for optimization. ILogicalConstruct falseSuccessor = condition.FalseSuccessor; ILogicalConstruct trueSuccessor = condition.TrueSuccessor; HashSet <ISingleEntrySubGraph> falseSuccessorFrontier = dominatorTree.GetDominanceFrontier(falseSuccessor); HashSet <ISingleEntrySubGraph> trueSuccessorFrontier = dominatorTree.GetDominanceFrontier(trueSuccessor); ILogicalConstruct exitSuccessor = CheckSuccessor(condition, trueSuccessor, falseSuccessorFrontier, dfsTree) ?? CheckSuccessor(condition, falseSuccessor, trueSuccessorFrontier, dfsTree); HashSet <ISingleEntrySubGraph> frontierIntersection = new HashSet <ISingleEntrySubGraph>(trueSuccessorFrontier); frontierIntersection.IntersectWith(falseSuccessorFrontier); if (exitSuccessor == null && falseSuccessorFrontier.Count > 0 && trueSuccessorFrontier.Count > 0 && frontierIntersection.Count == 0) { //If none of the successors can be a proper exit and the false and true successor frontiers are not empty but have no common node, //then we do not make the if since it will not have a common exit. return(false); } HashSet <ILogicalConstruct> thenBody = GetBlockBody(dominatorTree, trueSuccessor, condition); HashSet <ILogicalConstruct> elseBody = GetBlockBody(dominatorTree, falseSuccessor, condition); if (thenBody == null && elseBody == null) { return(false); } else if (thenBody == null) { condition.Negate(typeSystem); ILogicalConstruct swapHelper = trueSuccessor; trueSuccessor = falseSuccessor; falseSuccessor = swapHelper; thenBody = elseBody; elseBody = null; } //If the else body is null but the false successor is not a successor of the then body then we do not make the if. if (elseBody == null && !CheckSuccessors(thenBody, falseSuccessor)) { return(false); } if (ShouldInvertIfAndRemoveElse(thenBody, trueSuccessor, elseBody, falseSuccessor)) { ///This is performed for cosmetic reasons. condition.Negate(typeSystem); ILogicalConstruct successorSwapHelper = trueSuccessor; trueSuccessor = falseSuccessor; falseSuccessor = successorSwapHelper; HashSet <ILogicalConstruct> swapHelper = thenBody; thenBody = elseBody; elseBody = swapHelper; elseBody = null; } if (elseBody != null && !HasSuccessors(thenBody) && SubtreeEndsInInstructionCode(trueSuccessor.FirstBlock.TheBlock, new Code[] { Code.Ret, Code.Throw })) // check if all ends are throw and/or return -> allow mixed ends as well { // we don't need the else elseBody = null; } BlockLogicalConstruct theThenBlock = new BlockLogicalConstruct(trueSuccessor, thenBody); BlockLogicalConstruct theElseBlock = elseBody != null ? new BlockLogicalConstruct(falseSuccessor, elseBody) : null; IfLogicalConstruct theIfConstruct = IfLogicalConstruct.GroupInIfConstruct(condition, theThenBlock, theElseBlock); UpdateDominatorTree(dominatorTree, theIfConstruct); return(true); }
/// <summary> /// Gets the dominated nodes of the condition successor, only if they can form a legal block for the if construct. /// </summary> /// <param name="dominatorTree"></param> /// <param name="conditionSuccessor"></param> /// <returns>On success - a set of the nodes fo the block. Otherwise it returns null.</returns> private HashSet <ILogicalConstruct> GetBlockBody(DominatorTree dominatorTree, ILogicalConstruct conditionSuccessor, ConditionLogicalConstruct theCondition) { if (conditionSuccessor == dominatorTree.RootConstruct) //Corner case - the successor cannot be the entry of the construct. { return(null); } HashSet <ILogicalConstruct> body = null; if (conditionSuccessor.AllPredecessors.Count == 1) //The condition successor must have only one predecessor - the condition. { body = new HashSet <ILogicalConstruct>(); foreach (ILogicalConstruct node in dominatorTree.GetDominatedNodes(conditionSuccessor)) { if (node == theCondition) { return(null); } body.Add(node); } } return(body); }
private HashSet <ILogicalConstruct> GetBlockBody(DominatorTree dominatorTree, ILogicalConstruct conditionSuccessor, ConditionLogicalConstruct theCondition) { if (conditionSuccessor == dominatorTree.get_RootConstruct()) { return(null); } V_0 = null; if (conditionSuccessor.get_AllPredecessors().get_Count() == 1) { V_0 = new HashSet <ILogicalConstruct>(); V_1 = dominatorTree.GetDominatedNodes(conditionSuccessor).GetEnumerator(); try { while (V_1.MoveNext()) { V_2 = (ILogicalConstruct)V_1.get_Current(); if (V_2 != theCondition) { dummyVar0 = V_0.Add(V_2); } else { V_3 = null; goto Label1; } } goto Label0; } finally { ((IDisposable)V_1).Dispose(); } Label1: return(V_3); } Label0: return(V_0); }
/// <summary> /// Creates a new IfLogicalConstruct and adds it to the logical tree. /// </summary> /// <param name="condition">The condition of the if.</param> /// <param name="theThenBlock">The then block of the if.</param> /// <param name="theElseBlock">The else block of the if.</param> /// <returns>The created if construct.</returns> public static IfLogicalConstruct GroupInIfConstruct(ConditionLogicalConstruct condition, BlockLogicalConstruct theThenBlock, BlockLogicalConstruct theElseBlock) { return(new IfLogicalConstruct(condition, theThenBlock, theElseBlock)); }
/// <summary> /// Tries to build an if construct with condition - the specified condition. /// </summary> /// <remarks> /// The idea is to get the dominated nodes of the true successor to create the then block and the dominated nodes of the false successor /// to create the else block. /// If both the then and else blocks have successors, then they must have a common successor to create the if construct. /// </remarks> /// <param name="condition"></param> /// <returns>True on success.</returns> private bool TryBuildIfConstruct(ConditionLogicalConstruct condition, DominatorTree dominatorTree, DFSTree dfsTree) { //Store the true and false successors for optimization. ILogicalConstruct falseSuccessor = condition.FalseSuccessor; ILogicalConstruct trueSuccessor = condition.TrueSuccessor; HashSet<ISingleEntrySubGraph> falseSuccessorFrontier = dominatorTree.GetDominanceFrontier(falseSuccessor); HashSet<ISingleEntrySubGraph> trueSuccessorFrontier = dominatorTree.GetDominanceFrontier(trueSuccessor); ILogicalConstruct exitSuccessor = CheckSuccessor(condition, trueSuccessor, falseSuccessorFrontier, dfsTree) ?? CheckSuccessor(condition, falseSuccessor, trueSuccessorFrontier, dfsTree); HashSet<ISingleEntrySubGraph> frontierIntersection = new HashSet<ISingleEntrySubGraph>(trueSuccessorFrontier); frontierIntersection.IntersectWith(falseSuccessorFrontier); if (exitSuccessor == null && falseSuccessorFrontier.Count > 0 && trueSuccessorFrontier.Count > 0 && frontierIntersection.Count == 0) { //If none of the successors can be a proper exit and the false and true successor frontiers are not empty but have no common node, //then we do not make the if since it will not have a common exit. return false; } HashSet<ILogicalConstruct> thenBody = GetBlockBody(dominatorTree, trueSuccessor, condition); HashSet<ILogicalConstruct> elseBody = GetBlockBody(dominatorTree, falseSuccessor, condition); if (thenBody == null && elseBody == null) { return false; } else if(thenBody == null) { condition.Negate(typeSystem); ILogicalConstruct swapHelper = trueSuccessor; trueSuccessor = falseSuccessor; falseSuccessor = swapHelper; thenBody = elseBody; elseBody = null; } //If the else body is null but the false successor is not a successor of the then body then we do not make the if. if(elseBody == null && !CheckSuccessors(thenBody, falseSuccessor)) { return false; } if (ShouldInvertIfAndRemoveElse(thenBody, trueSuccessor, elseBody, falseSuccessor)) { ///This is performed for cosmetic reasons. condition.Negate(typeSystem); ILogicalConstruct successorSwapHelper = trueSuccessor; trueSuccessor = falseSuccessor; falseSuccessor = successorSwapHelper; HashSet<ILogicalConstruct> swapHelper = thenBody; thenBody = elseBody; elseBody = swapHelper; elseBody = null; } if (elseBody != null && !HasSuccessors(thenBody) && SubtreeEndsInInstructionCode(trueSuccessor.FirstBlock.TheBlock,new Code[]{Code.Ret, Code.Throw})) // check if all ends are throw and/or return -> allow mixed ends as well { // we don't need the else elseBody = null; } BlockLogicalConstruct theThenBlock = new BlockLogicalConstruct(trueSuccessor, thenBody); BlockLogicalConstruct theElseBlock = elseBody != null ? new BlockLogicalConstruct(falseSuccessor, elseBody) : null; IfLogicalConstruct theIfConstruct = IfLogicalConstruct.GroupInIfConstruct(condition, theThenBlock, theElseBlock); UpdateDominatorTree(dominatorTree, theIfConstruct); return true; }
/// <summary> /// Determines the type of the loop and the condition of the loop. Adds additional nodes into the loop body. /// </summary> /// <param name="loopBody"></param> /// <param name="header"></param> /// <param name="latchingNodes"></param> /// <param name="interval"></param> /// <param name="loopCondition"></param> /// <returns></returns> private LoopType DetermineLoopType(HashSet<ILogicalConstruct> loopBody, HashSet<ILogicalConstruct> latchingNodes, IntervalConstruct interval, DominatorTree dominatorTree, out ConditionLogicalConstruct loopCondition) { ILogicalConstruct header = interval.Entry as ILogicalConstruct; HashSet<ILogicalConstruct> legalExits = new HashSet<ILogicalConstruct>(latchingNodes); legalExits.Add(header); ILogicalConstruct parentConstruct = header.Parent as ILogicalConstruct; DFSTree dfsTree = DFSTBuilder.BuildTree(parentConstruct); //B - nodes in the loop body (= loopBody) //I - nodes in the interval (= interval.Children) //U - union of all of the dominance frontiers of the nodes in B //exitDominanceFrontier = (U n I) \ B //If a node is in the exitDominanceFrontier, then it is dominated by the header and is a successor (not necessarily direct) of more than one //node in the loop body. HashSet<ILogicalConstruct> exitDominanceFrontier = new HashSet<ILogicalConstruct>(); foreach (ILogicalConstruct loopNode in loopBody) { foreach (ILogicalConstruct frontierNode in dominatorTree.GetDominanceFrontier(loopNode)) { if (interval.Children.Contains(frontierNode) && !loopBody.Contains(frontierNode)) { exitDominanceFrontier.Add(frontierNode); } } } //This is leftover heuristic, that was used for determining a suitable successor that is going to be follow node of the loop. //Changing it now will break a good number of the tests. Since the produced output is acceptable, until a better heuristic is found //there is no need to change it. if (exitDominanceFrontier.Count == 0) { //If the exit dominance frontier is empty then we look for the node, with minimum post order index, that is a successor of a condition loop exit. //The desired exit should be a condition in order to reduce the number of infinite loops (heuristic). foreach (DFSTNode dfsNode in dfsTree.ReversePostOrder) { ILogicalConstruct construct = dfsNode.Construct as ILogicalConstruct; if (loopBody.Contains(construct)) { continue; } loopCondition = GetLoopConditionWithMaxIndex(dfsTree, loopBody, legalExits, construct); //By taking the successor with the minimum post order index and the loop exit with the maximum post order index, we ensure that //the produced construct will always be the same, since the post order in our case is a total order. //There are other various ways of finding the exit-successor pair that can bring consistent output, but none of them is found to yield //better results than the rest. if (loopCondition != null) { //We expand the loop body only when we've found a condition successor of the loop. //This is done in order to avoid adding all of the dominated nodes of an infinite loop to the body. (Better readability of the final code.) //E.g.: An infinite loop on the top level of the logical tree (i.e. child of the method block construct). If it dominates all of its //succeeding nodes then they will be in its interval, which means that they will be added to the loop. As a result there will //be an infinite loop at the end of the method, that encloses a cood part of the code, for no apparent reason. ExpandLoopBody(interval, loopBody, construct); if (loopCondition == header) { return LoopType.PreTestedLoop; } else { return LoopType.PostTestedLoop; } } } if (CanBeLoopCondition(header, loopBody)) { loopCondition = header as ConditionLogicalConstruct; return LoopType.PreTestedLoop; } else { loopCondition = null; return LoopType.InfiniteLoop; } } else { //If there are nodes in the exitDominanceFrontier, then we choose the one with the minimum postorder index for successor of the loop. //Then we try to find a condition exit of the loop, with maximum post order index, that is predecessor of the successor node. int minOrderIndexOfSuccessor = dfsTree.ReversePostOrder.Count; foreach (ILogicalConstruct successor in exitDominanceFrontier) { int currentOrderIndex = dfsTree.ConstructToNodeMap[successor].ReversePostOrderIndex; if(currentOrderIndex < minOrderIndexOfSuccessor) { minOrderIndexOfSuccessor = currentOrderIndex; } } ILogicalConstruct loopSuccessor = dfsTree.ReversePostOrder[minOrderIndexOfSuccessor].Construct as ILogicalConstruct; loopCondition = GetLoopConditionWithMaxIndex(dfsTree, loopBody, legalExits, loopSuccessor); ExpandLoopBody(interval, loopBody, loopSuccessor); if (loopCondition != null) { if (loopCondition == header) { return LoopType.PreTestedLoop; } else { return LoopType.PostTestedLoop; } } else { return LoopType.InfiniteLoop; } } }
/// <summary> /// Gets the dominated nodes of the condition successor, only if they can form a legal block for the if construct. /// </summary> /// <param name="dominatorTree"></param> /// <param name="conditionSuccessor"></param> /// <returns>On success - a set of the nodes fo the block. Otherwise it returns null.</returns> private HashSet<ILogicalConstruct> GetBlockBody(DominatorTree dominatorTree, ILogicalConstruct conditionSuccessor, ConditionLogicalConstruct theCondition) { if(conditionSuccessor == dominatorTree.RootConstruct) //Corner case - the successor cannot be the entry of the construct. { return null; } HashSet<ILogicalConstruct> body = null; if(conditionSuccessor.AllPredecessors.Count == 1) //The condition successor must have only one predecessor - the condition. { body = new HashSet<ILogicalConstruct>(); foreach (ILogicalConstruct node in dominatorTree.GetDominatedNodes(conditionSuccessor)) { if (node == theCondition) { return null; } body.Add(node); } } return body; }
/// <summary> /// Tries to create a new complex condition starting from the specified. /// </summary> /// <param name="conditionNode"></param> /// <returns></returns> private ConditionLogicalConstruct CreateComplexCondition(ConditionLogicalConstruct conditionNode) { //Explanation: // // A // / \ // B-> C (A -> B, C; B -> C, ...; C -> ...) // / //A and B - condition nodes, C - common successor // //This is the representation of every short-circuit boolean expression. Depending on the relation between the conditions, all possible complex //boolean expressions can be made. After we've made the new condition from A and B we can continue the check for this type of construction from the //new node. //So, the purpose of the implemented algorithm is to find the "chain" (directed path containing all the nodes) of all nodes that //can be made into a complex condition. The reason for this is to reduce the creating of new logical constructs. //Holds the complex condition that we have found so far. Expression complexExpression = conditionNode.ConditionExpression; //Holds all the nodes that form the complex condition. HashSet<ILogicalConstruct> conditionNodes = new HashSet<ILogicalConstruct>(); //Holds the last node in the "chain", since it's successors are the successors of the complex condition. ConditionLogicalConstruct lastNode = conditionNode; conditionNodes.Add(lastNode); //The true successor of the complex condition. ILogicalConstruct trueSuccessor = lastNode.TrueSuccessor; //The false successor of the complex condition. ILogicalConstruct falseSuccessor = lastNode.FalseSuccessor; while(true) { ConditionLogicalConstruct newConditionNode; ILogicalConstruct commonSuccessor; BinaryOperator @operator; if (CanBePartOfComplexCondition(trueSuccessor, conditionNodes, lastNode.FalseCFGSuccessor)) { //If the true successor can be added, then the common successor is the false node. newConditionNode = trueSuccessor as ConditionLogicalConstruct; commonSuccessor = falseSuccessor; //This check is to ensure that the common successor is the false successor to both the nodes. if (newConditionNode.FalseSuccessor != commonSuccessor) { newConditionNode.Negate(typeSystem); } //Since both of the conditions have the common successor as false successor, then the binary operation is &&. @operator = BinaryOperator.LogicalAnd; } else if (CanBePartOfComplexCondition(falseSuccessor, conditionNodes, lastNode.TrueCFGSuccessor)) { //If the false successor can be added, then the common successor is the true node. newConditionNode = falseSuccessor as ConditionLogicalConstruct; commonSuccessor = trueSuccessor; //This check is to ensure that the common successor is the true successor to both the nodes. if (newConditionNode.TrueSuccessor != commonSuccessor) { newConditionNode.Negate(typeSystem); } //Since both of the conditions have the common successor as the true successor, then the binary operation is ||. @operator = BinaryOperator.LogicalOr; } else { //If we cannot add any of the successors to the condition, we finish the search. break; } //Update the variables. complexExpression = new BinaryExpression(@operator, complexExpression, newConditionNode.ConditionExpression, typeSystem, null); complexExpression.ExpressionType = booleanTypeReference; lastNode = newConditionNode; trueSuccessor = lastNode.TrueSuccessor; falseSuccessor = lastNode.FalseSuccessor; conditionNodes.Add(lastNode); } //If we haven't found any other nodes, we return the original condition construct. if(conditionNodes.Count == 1) { return conditionNode; } //Otherwise we make the new construct and return it. HashSet<ConditionLogicalConstruct> complexConditionNodes = new HashSet<ConditionLogicalConstruct>(); foreach (ConditionLogicalConstruct conditionChild in conditionNodes) { complexConditionNodes.Add(conditionChild); } return new ConditionLogicalConstruct(conditionNode, lastNode, complexConditionNodes, complexExpression); }
/// <summary> /// Creates a new IfLogicalConstruct and adds it to the logical tree. /// </summary> /// <param name="condition">The condition of the if.</param> /// <param name="theThenBlock">The then block of the if.</param> /// <param name="theElseBlock">The else block of the if.</param> /// <returns>The created if construct.</returns> public static IfLogicalConstruct GroupInIfConstruct(ConditionLogicalConstruct condition, BlockLogicalConstruct theThenBlock, BlockLogicalConstruct theElseBlock) { return new IfLogicalConstruct(condition, theThenBlock, theElseBlock); }
private bool TryBuildIfConstruct(ConditionLogicalConstruct condition, DominatorTree dominatorTree, DFSTree dfsTree) { V_0 = condition.get_FalseSuccessor(); V_1 = condition.get_TrueSuccessor(); V_2 = dominatorTree.GetDominanceFrontier(V_0); V_3 = dominatorTree.GetDominanceFrontier(V_1); stackVariable15 = this.CheckSuccessor(condition, V_1, V_2, dfsTree); if (stackVariable15 == null) { dummyVar0 = stackVariable15; stackVariable15 = this.CheckSuccessor(condition, V_0, V_3, dfsTree); } V_4 = new HashSet <ISingleEntrySubGraph>(V_3); V_4.IntersectWith(V_2); if (stackVariable15 == null && V_2.get_Count() > 0 && V_3.get_Count() > 0 && V_4.get_Count() == 0) { return(false); } V_5 = this.GetBlockBody(dominatorTree, V_1, condition); V_6 = this.GetBlockBody(dominatorTree, V_0, condition); if (V_5 == null && V_6 == null) { return(false); } if (V_5 == null) { condition.Negate(this.typeSystem); stackVariable86 = V_1; V_1 = V_0; V_0 = stackVariable86; V_5 = V_6; V_6 = null; } if (V_6 == null && !this.CheckSuccessors(V_5, V_0)) { return(false); } if (this.ShouldInvertIfAndRemoveElse(V_5, V_1, V_6, V_0)) { condition.Negate(this.typeSystem); stackVariable73 = V_1; V_1 = V_0; V_0 = stackVariable73; stackVariable75 = V_5; V_5 = V_6; V_6 = stackVariable75; V_6 = null; } if (V_6 != null && !this.HasSuccessors(V_5)) { stackVariable61 = V_1.get_FirstBlock().get_TheBlock(); stackVariable63 = new Code[2]; stackVariable63[0] = 41; stackVariable63[1] = 119; if (this.SubtreeEndsInInstructionCode(stackVariable61, stackVariable63)) { V_6 = null; } } V_7 = new BlockLogicalConstruct(V_1, V_5); if (V_6 != null) { stackVariable46 = new BlockLogicalConstruct(V_0, V_6); } else { stackVariable46 = null; } this.UpdateDominatorTree(dominatorTree, IfLogicalConstruct.GroupInIfConstruct(condition, V_7, stackVariable46)); return(true); }
/// <summary> /// Tries to create a new complex condition starting from the specified. /// </summary> /// <param name="conditionNode"></param> /// <returns></returns> private ConditionLogicalConstruct CreateComplexCondition(ConditionLogicalConstruct conditionNode) { //Explanation: // // A // / \ // B-> C (A -> B, C; B -> C, ...; C -> ...) // / //A and B - condition nodes, C - common successor // //This is the representation of every short-circuit boolean expression. Depending on the relation between the conditions, all possible complex //boolean expressions can be made. After we've made the new condition from A and B we can continue the check for this type of construction from the //new node. //So, the purpose of the implemented algorithm is to find the "chain" (directed path containing all the nodes) of all nodes that //can be made into a complex condition. The reason for this is to reduce the creating of new logical constructs. //Holds the complex condition that we have found so far. Expression complexExpression = conditionNode.ConditionExpression; //Holds all the nodes that form the complex condition. HashSet <ILogicalConstruct> conditionNodes = new HashSet <ILogicalConstruct>(); //Holds the last node in the "chain", since it's successors are the successors of the complex condition. ConditionLogicalConstruct lastNode = conditionNode; conditionNodes.Add(lastNode); //The true successor of the complex condition. ILogicalConstruct trueSuccessor = lastNode.TrueSuccessor; //The false successor of the complex condition. ILogicalConstruct falseSuccessor = lastNode.FalseSuccessor; while (true) { ConditionLogicalConstruct newConditionNode; ILogicalConstruct commonSuccessor; BinaryOperator @operator; if (CanBePartOfComplexCondition(trueSuccessor, conditionNodes, lastNode.FalseCFGSuccessor)) { //If the true successor can be added, then the common successor is the false node. newConditionNode = trueSuccessor as ConditionLogicalConstruct; commonSuccessor = falseSuccessor; //This check is to ensure that the common successor is the false successor to both the nodes. if (newConditionNode.FalseSuccessor != commonSuccessor) { newConditionNode.Negate(typeSystem); } //Since both of the conditions have the common successor as false successor, then the binary operation is &&. @operator = BinaryOperator.LogicalAnd; } else if (CanBePartOfComplexCondition(falseSuccessor, conditionNodes, lastNode.TrueCFGSuccessor)) { //If the false successor can be added, then the common successor is the true node. newConditionNode = falseSuccessor as ConditionLogicalConstruct; commonSuccessor = trueSuccessor; //This check is to ensure that the common successor is the true successor to both the nodes. if (newConditionNode.TrueSuccessor != commonSuccessor) { newConditionNode.Negate(typeSystem); } //Since both of the conditions have the common successor as the true successor, then the binary operation is ||. @operator = BinaryOperator.LogicalOr; } else { //If we cannot add any of the successors to the condition, we finish the search. break; } //Update the variables. complexExpression = new BinaryExpression(@operator, complexExpression, newConditionNode.ConditionExpression, typeSystem, null); complexExpression.ExpressionType = booleanTypeReference; lastNode = newConditionNode; trueSuccessor = lastNode.TrueSuccessor; falseSuccessor = lastNode.FalseSuccessor; conditionNodes.Add(lastNode); } //If we haven't found any other nodes, we return the original condition construct. if (conditionNodes.Count == 1) { return(conditionNode); } //Otherwise we make the new construct and return it. HashSet <ConditionLogicalConstruct> complexConditionNodes = new HashSet <ConditionLogicalConstruct>(); foreach (ConditionLogicalConstruct conditionChild in conditionNodes) { complexConditionNodes.Add(conditionChild); } return(new ConditionLogicalConstruct(conditionNode, lastNode, complexConditionNodes, complexExpression)); }