/// <summary> /// Determines the follow nodes in the given subgraph. /// </summary> /// <remarks> /// Every node can follow only one node. /// Everey node can be followed by only one node. /// The follow node relation cannot form a back edge. (i.e. B can be the follow node of A <=> (A, B) is not a backedge) /// Let G = (V, E) be the original graph. /// Let G' = (V, E') be the subgraph of G, where E' = E \ { e | e is from E && e is backedge in the DFS traversal }. /// /// The solution is to find a cover of vertex-disjoint paths of G' that will yield the minimum number of gotos. /// The gotos will be the edges that are not in the cover. So we want the edges that will yeild the greatest number of gotos to /// be in the cover. If we find a good weight function for the edges in the graph (i.e. correctly determines how much gotos there will be between /// two nodes), then all we have to do is find a cover of vertex-disjoint paths of G' with maximum total weight. /// </remarks> /// <param name="theGraph"></param> private void DetermineFollowNodesInSubGraph(ILogicalConstruct theGraph) { //Creates the adjacency matrix for the mentioned subgraph - G'. GetVerticesAndAdjacencyMatrix(theGraph); //Since no back edge is left in G', then G' is a DAG. List <KeyValuePair <int, int> > followEdges = MaxWeightDisjointPathsFinder.GetOptimalEdgesInDAG(adjacencyMatrix); foreach (KeyValuePair <int, int> followEdge in followEdges) { orderedVertexArray[followEdge.Key].CFGFollowNode = orderedVertexArray[followEdge.Value].FirstBlock; if (orderedVertexArray[followEdge.Key] is ConditionLogicalConstruct) { ConditionLogicalConstruct theCondition = orderedVertexArray[followEdge.Key] as ConditionLogicalConstruct; if (theCondition.CFGFollowNode == theCondition.TrueCFGSuccessor) { //If the follow node of a condition construct is the true successor, then we need to negate the condition construct. theCondition.Negate(typeSystem); } } } }
/// <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 ProcessLogicalConstruct(ILogicalConstruct theConstruct) { if (theConstruct is BlockLogicalConstruct) { ILogicalConstruct current = (ILogicalConstruct)theConstruct.Entry; while (current != null) { ProcessLogicalConstruct(current); if (visitedConstructs.Contains(current.FollowNode)) { current.CFGFollowNode = null; } current = current.FollowNode; } ProcessGotoFlowConstructs(theConstruct as BlockLogicalConstruct); } else if (theConstruct is ExceptionHandlingLogicalConstruct) { ProcessLogicalConstruct((theConstruct as ExceptionHandlingLogicalConstruct).Try); if (theConstruct is TryCatchFilterLogicalConstruct) { foreach (IFilteringExceptionHandler handler in (theConstruct as TryCatchFilterLogicalConstruct).Handlers) { if (handler.HandlerType == FilteringExceptionHandlerType.Filter) { ProcessLogicalConstruct((handler as ExceptionHandlingBlockFilter).Filter); ProcessLogicalConstruct((handler as ExceptionHandlingBlockFilter).Handler); } else if (handler.HandlerType == FilteringExceptionHandlerType.Catch) { ProcessLogicalConstruct((handler as ExceptionHandlingBlockCatch)); } } } else if (theConstruct is TryFaultLogicalConstruct) { ProcessLogicalConstruct((theConstruct as TryFaultLogicalConstruct).Fault); } else if (theConstruct is TryFinallyLogicalConstruct) { ProcessLogicalConstruct((theConstruct as TryFinallyLogicalConstruct).Finally); } } else if (theConstruct is IfLogicalConstruct) { IfLogicalConstruct theIf = theConstruct as IfLogicalConstruct; ProcessLogicalConstruct(theIf.Then); if (theIf.Else != null) { ProcessLogicalConstruct(theIf.Else); } } else if (theConstruct is LoopLogicalConstruct) { LoopLogicalConstruct theLogicalLoop = theConstruct as LoopLogicalConstruct; ProcessLogicalConstruct(theLogicalLoop.LoopBodyBlock); ProcessLogicalConstruct(theLogicalLoop.LoopCondition); } else if (theConstruct is SwitchLogicalConstruct) { SwitchLogicalConstruct theLogicalSwitch = theConstruct as SwitchLogicalConstruct; foreach (CaseLogicalConstruct @case in theLogicalSwitch.ConditionCases) { ProcessLogicalConstruct(@case); } ProcessLogicalConstruct(theLogicalSwitch.DefaultCase); } else if (theConstruct is ConditionLogicalConstruct) { ConditionLogicalConstruct clc = theConstruct as ConditionLogicalConstruct; ProcessLogicalConstruct(clc.FirstBlock); } visitedConstructs.Add(theConstruct); }
private LoopType DetermineLoopType(HashSet <ILogicalConstruct> loopBody, HashSet <ILogicalConstruct> latchingNodes, IntervalConstruct interval, DominatorTree dominatorTree, out ConditionLogicalConstruct loopCondition) { V_0 = interval.get_Entry() as ILogicalConstruct; V_1 = new HashSet <ILogicalConstruct>(latchingNodes); dummyVar0 = V_1.Add(V_0); V_2 = DFSTBuilder.BuildTree(V_0.get_Parent() as ILogicalConstruct); V_3 = new HashSet <ILogicalConstruct>(); V_4 = loopBody.GetEnumerator(); try { while (V_4.MoveNext()) { V_5 = V_4.get_Current(); V_6 = dominatorTree.GetDominanceFrontier(V_5).GetEnumerator(); try { while (V_6.MoveNext()) { V_7 = (ILogicalConstruct)V_6.get_Current(); if (!interval.get_Children().Contains(V_7) || loopBody.Contains(V_7)) { continue; } dummyVar1 = V_3.Add(V_7); } } finally { ((IDisposable)V_6).Dispose(); } } } finally { ((IDisposable)V_4).Dispose(); } if (V_3.get_Count() == 0) { V_8 = V_2.get_ReversePostOrder().GetEnumerator(); try { while (V_8.MoveNext()) { V_9 = V_8.get_Current().get_Construct() as ILogicalConstruct; if (loopBody.Contains(V_9)) { continue; } loopCondition = this.GetLoopConditionWithMaxIndex(V_2, loopBody, V_1, V_9); if (loopCondition == null) { continue; } this.ExpandLoopBody(interval, loopBody, V_9); if (loopCondition != V_0) { V_10 = 2; goto Label1; } else { V_10 = 1; goto Label1; } } goto Label0; } finally { ((IDisposable)V_8).Dispose(); } Label1: return(V_10); } V_11 = V_2.get_ReversePostOrder().get_Count(); V_4 = V_3.GetEnumerator(); try { while (V_4.MoveNext()) { V_13 = V_4.get_Current(); V_14 = V_2.get_ConstructToNodeMap().get_Item(V_13).get_ReversePostOrderIndex(); if (V_14 >= V_11) { continue; } V_11 = V_14; } } finally { ((IDisposable)V_4).Dispose(); } V_12 = V_2.get_ReversePostOrder().get_Item(V_11).get_Construct() as ILogicalConstruct; loopCondition = this.GetLoopConditionWithMaxIndex(V_2, loopBody, V_1, V_12); this.ExpandLoopBody(interval, loopBody, V_12); if (loopCondition == null) { return(0); } if (loopCondition == V_0) { return(1); } return(2); Label0: if (!this.CanBeLoopCondition(V_0, loopBody)) { loopCondition = null; return(0); } loopCondition = V_0 as ConditionLogicalConstruct; return(1); }
public LoopLogicalConstruct(ILogicalConstruct entry, HashSet <ILogicalConstruct> loopBody, Telerik.JustDecompiler.Decompiler.LogicFlow.Loops.LoopType loopType, ConditionLogicalConstruct loopCondition, TypeSystem typeSystem) { base(); if (loopCondition != null) { loopCondition.set_LogicalContainer(this); } this.set_LoopType(loopType); this.set_LoopCondition(loopCondition); if (this.get_LoopType() != Telerik.JustDecompiler.Decompiler.LogicFlow.Loops.LoopType.InfiniteLoop) { dummyVar0 = loopBody.Remove(this.get_LoopCondition()); } this.DetermineLoopBodyBlock(entry, loopBody); this.RedirectChildrenToNewParent(this.GetLoopChildrenCollection()); this.FixLoopCondition(typeSystem); return; }
/// <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); } } }