Beispiel #1
0
 private void SetTrueAndFalseSuccessors(CFGBlockLogicalConstruct cfgConditionBlock)
 {
     stackVariable1 = cfgConditionBlock.get_TheBlock();
     V_0            = stackVariable1.get_Successors()[0];
     V_1            = stackVariable1.get_Successors()[1];
     V_2            = cfgConditionBlock.get_CFGSuccessors().GetEnumerator();
     try
     {
         while (V_2.MoveNext())
         {
             V_3 = V_2.get_Current();
             if (InstructionBlock.op_Equality(V_3.get_TheBlock(), V_0))
             {
                 this.set_TrueCFGSuccessor(V_3);
             }
             if (!InstructionBlock.op_Equality(V_3.get_TheBlock(), V_1))
             {
                 continue;
             }
             this.set_FalseCFGSuccessor(V_3);
         }
     }
     finally
     {
         ((IDisposable)V_2).Dispose();
     }
     return;
 }
Beispiel #2
0
 private void ManageSuccessorInCaseOfLoop(CFGBlockLogicalConstruct cfgSuccessor)
 {
     if (this.get_FirstBlock() == cfgSuccessor)
     {
         this.AddToSuccessors(cfgSuccessor);
         V_0 = this.get_Children().GetEnumerator();
         try
         {
             while (V_0.MoveNext())
             {
                 V_1 = (CFGBlockLogicalConstruct)V_0.get_Current();
                 if (!V_1.get_CFGSuccessors().Contains(cfgSuccessor))
                 {
                     continue;
                 }
                 this.AddToPredecessors(V_1);
             }
         }
         finally
         {
             ((IDisposable)V_0).Dispose();
         }
     }
     return;
 }
        /// <summary>
        /// Negates the expression of the construct and switches the true and false successors.
        /// </summary>
        public void Negate(TypeSystem typeSystem)
        {
            CFGBlockLogicalConstruct successorHolder = TrueCFGSuccessor;

            TrueCFGSuccessor  = FalseCFGSuccessor;
            FalseCFGSuccessor = successorHolder;

            ConditionExpression = Negator.Negate(ConditionExpression, typeSystem);
        }
Beispiel #4
0
        private bool AllEndsAreThrow(ILogicalConstruct entry)
        {
            CFGBlockLogicalConstruct entryBlock = entry.FirstBlock;

            if (!SubtreeEndsInInstructionCode(entryBlock.TheBlock, new Code[] { Code.Throw }))
            {
                return(false);
            }
            return(true);
        }
 private void MapSwitchBlocksToParents()
 {
     foreach (InstructionBlock instructionBlock in logicalContext.CFG.SwitchBlocksInformation.Keys)
     {
         CFGBlockLogicalConstruct[] constructs = logicalContext.CFGBlockToLogicalConstructMap[instructionBlock];
         //We get the last CFG construct since it will hold the condition of the switch and its successors.
         CFGBlockLogicalConstruct instructionBlockConstruct = constructs[constructs.Length - 1];
         AddSwitchCFGBlockToMap(instructionBlockConstruct);
     }
 }
 private void AddSwitchCFGBlockToMap(CFGBlockLogicalConstruct cfgConstruct)
 {
     V_0 = cfgConstruct.get_Parent() as ILogicalConstruct;
     if (!this.logicalConstructToSwitchBlocksMap.TryGetValue(V_0, out V_1))
     {
         V_1 = new List <CFGBlockLogicalConstruct>();
         this.logicalConstructToSwitchBlocksMap.Add(V_0, V_1);
     }
     V_1.Add(cfgConstruct);
     return;
 }
        private void AddSwitchCFGBlockToMap(CFGBlockLogicalConstruct cfgConstruct)
        {
            ILogicalConstruct parentConstruct = cfgConstruct.Parent as ILogicalConstruct;
            List<CFGBlockLogicalConstruct> switchCFGConstructs;
            if (!logicalConstructToSwitchBlocksMap.TryGetValue(parentConstruct, out switchCFGConstructs))
            {
                switchCFGConstructs = new List<CFGBlockLogicalConstruct>();
                logicalConstructToSwitchBlocksMap.Add(parentConstruct, switchCFGConstructs);
            }

            switchCFGConstructs.Add(cfgConstruct);
        }
        private void AddSwitchCFGBlockToMap(CFGBlockLogicalConstruct cfgConstruct)
        {
            ILogicalConstruct parentConstruct = cfgConstruct.Parent as ILogicalConstruct;
            List <CFGBlockLogicalConstruct> switchCFGConstructs;

            if (!logicalConstructToSwitchBlocksMap.TryGetValue(parentConstruct, out switchCFGConstructs))
            {
                switchCFGConstructs = new List <CFGBlockLogicalConstruct>();
                logicalConstructToSwitchBlocksMap.Add(parentConstruct, switchCFGConstructs);
            }

            switchCFGConstructs.Add(cfgConstruct);
        }
Beispiel #9
0
 private ConditionLogicalConstruct(CFGBlockLogicalConstruct cfgConditionBlock)
 {
     base();
     this.set_Entry(cfgConditionBlock);
     this.SetTrueAndFalseSuccessors(cfgConditionBlock);
     this.set_ConditionExpression(cfgConditionBlock.get_LogicalConstructExpressions().get_Item(0));
     stackVariable12    = new ILogicalConstruct[1];
     stackVariable12[0] = cfgConditionBlock;
     this.RedirectChildrenToNewParent((IEnumerable <ILogicalConstruct>)stackVariable12);
     this.AddTrueFalseSuccessors();
     this.set_LogicalContainer(null);
     return;
 }
        private ConditionLogicalConstruct(CFGBlockLogicalConstruct cfgConditionBlock)
        {
            Entry = cfgConditionBlock;

            SetTrueAndFalseSuccessors(cfgConditionBlock);

            ConditionExpression = cfgConditionBlock.LogicalConstructExpressions[0];

            RedirectChildrenToNewParent(new ILogicalConstruct[] { cfgConditionBlock });

            AddTrueFalseSuccessors();

            LogicalContainer = null;
        }
 /// <summary>
 /// If the given successor is the entry of the condition we update the predecessor and successor collections of the condition.
 /// </summary>
 /// <param name="cfgSuccessor"></param>
 private void ManageSuccessorInCaseOfLoop(CFGBlockLogicalConstruct cfgSuccessor)
 {
     if (this.FirstBlock == cfgSuccessor)
     {
         this.AddToSuccessors(cfgSuccessor);
         foreach (CFGBlockLogicalConstruct cfgChild in this.Children)
         {
             if (cfgChild.CFGSuccessors.Contains(cfgSuccessor))
             {
                 this.AddToPredecessors(cfgChild);
             }
         }
     }
 }
        private ConditionLogicalConstruct(CFGBlockLogicalConstruct cfgConditionBlock)
        {
            Entry = cfgConditionBlock;

            SetTrueAndFalseSuccessors(cfgConditionBlock);

            ConditionExpression = cfgConditionBlock.LogicalConstructExpressions[0];

            RedirectChildrenToNewParent(new ILogicalConstruct[] { cfgConditionBlock });

            AddTrueFalseSuccessors();

			LogicalContainer = null;
        }
        /// <summary>
        /// Determines the weight of the given edge.
        /// </summary>
        /// <remarks>
        /// This is the heuristic part of the algorithm.
        /// The weight of an edge is determined by the number of CFG block constructs in the given <paramref name="start"/> construct,
        /// that have for successor the specified <paramref name="end"/> construct.
        /// </remarks>
        /// <param name="start"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        private int GetWeight(ILogicalConstruct start, ILogicalConstruct end)
        {
            int weight = 0;
            CFGBlockLogicalConstruct endCFGEntry = end.FirstBlock;

            foreach (CFGBlockLogicalConstruct cfgChild in start.CFGBlocks)
            {
                if (cfgChild.CFGSuccessors.Contains(endCFGEntry))
                {
                    weight++;
                }
            }

            return(weight);
        }
        private void CreateSwitchConstruct(CFGBlockLogicalConstruct switchBlock, ILogicalConstruct parentConstruct,
                                           SwitchData switchData, DominatorTree dominatorTree)
        {
            List <KeyValuePair <CFGBlockLogicalConstruct, List <int> > >    cfgSuccessorToLabelsMap           = GetOrderedCFGSuccessorToLabelsMap(switchData);
            Dictionary <ILogicalConstruct, HashSet <ISingleEntrySubGraph> > validCaseEntryToDominatedNodesMap = GetValidCases(dominatorTree, switchBlock);

            List <CaseLogicalConstruct> orderedCaseConstructs = new List <CaseLogicalConstruct>();
            PairList <List <int>, CFGBlockLogicalConstruct> labelsToCFGSuccessorsList = new PairList <List <int>, CFGBlockLogicalConstruct>();

            foreach (KeyValuePair <CFGBlockLogicalConstruct, List <int> > cfgSuccessorToLabelsPair in cfgSuccessorToLabelsMap)
            {
                ILogicalConstruct successor;
                HashSet <ISingleEntrySubGraph> dominatedNodes;
                if (LogicalFlowUtilities.TryGetParentConstructWithGivenParent(cfgSuccessorToLabelsPair.Key, parentConstruct, out successor) &&
                    validCaseEntryToDominatedNodesMap.TryGetValue(successor, out dominatedNodes))
                {
                    CaseLogicalConstruct newCaseConstruct = new CaseLogicalConstruct(successor);
                    newCaseConstruct.CaseNumbers.AddRange(cfgSuccessorToLabelsPair.Value);
                    newCaseConstruct.Body.UnionWith(dominatedNodes.Cast <ILogicalConstruct>());
                    newCaseConstruct.AttachCaseConstructToGraph();
                    orderedCaseConstructs.Add(newCaseConstruct);
                }
                else
                {
                    labelsToCFGSuccessorsList.Add(cfgSuccessorToLabelsPair.Value, cfgSuccessorToLabelsPair.Key);
                }
            }

            CaseLogicalConstruct           defaultCase         = null;
            CFGBlockLogicalConstruct       defaultCFGSuccessor = GetCFGLogicalConstructFromBlock(switchData.DefaultCase);
            ILogicalConstruct              defaultSuccessor;
            HashSet <ISingleEntrySubGraph> defaultCaseNodes;

            if (LogicalFlowUtilities.TryGetParentConstructWithGivenParent(defaultCFGSuccessor, parentConstruct, out defaultSuccessor) &&
                validCaseEntryToDominatedNodesMap.TryGetValue(defaultSuccessor, out defaultCaseNodes))
            {
                defaultCase = new CaseLogicalConstruct(defaultSuccessor);
                if (HasSuccessors(defaultCaseNodes))
                {
                    defaultCase.Body.UnionWith(defaultCaseNodes.Cast <ILogicalConstruct>());
                }
                defaultCase.AttachCaseConstructToGraph();
            }

            SwitchLogicalConstruct theSwitch = SwitchLogicalConstruct.GroupInSwitchConstruct(switchBlock, orderedCaseConstructs, labelsToCFGSuccessorsList, defaultCase, defaultCFGSuccessor);

            UpdateDominatorTree(dominatorTree, theSwitch);
        }
        ILogicalConstruct FindChildBlockBelongsTo(ILogicalConstruct parent, CFGBlockLogicalConstruct block)
        {
            ILogicalConstruct result = null, current = block;

            do
            {
                if (current.Parent == parent)
                {
                    result = current;
                    break;
                }

                current = (ILogicalConstruct)current.Parent;
            } while (current.Parent != null);

            return(result);
        }
 private SwitchLogicalConstruct(CFGBlockLogicalConstruct entry, ICollection <CaseLogicalConstruct> body, PairList <List <int>, CFGBlockLogicalConstruct> nonDominatedCFGSuccessors, CaseLogicalConstruct defaultCase, CFGBlockLogicalConstruct defaultCFGSuccessor)
 {
     base();
     this.set_SwitchConditionExpression(entry.get_LogicalConstructExpressions().get_Item(0));
     this.set_DefaultCase(defaultCase);
     this.set_DefaultCFGSuccessor(defaultCFGSuccessor);
     this.set_NonDominatedCFGSuccessors(nonDominatedCFGSuccessors);
     this.FillCasesArray(body);
     this.set_Entry(entry);
     this.RedirectChildrenToNewParent(this.GetBodyCollection());
     if (entry.get_CFGSuccessors().Contains(entry))
     {
         this.AddToPredecessors(entry);
         this.AddToSuccessors(entry);
     }
     return;
 }
 /// <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);
         }
     }
 }
        private void CreateSwitchConstruct(CFGBlockLogicalConstruct switchBlock, ILogicalConstruct parentConstruct,
            SwitchData switchData, DominatorTree dominatorTree)
        {
            List<KeyValuePair<CFGBlockLogicalConstruct, List<int>>> cfgSuccessorToLabelsMap = GetOrderedCFGSuccessorToLabelsMap(switchData);
            Dictionary<ILogicalConstruct, HashSet<ISingleEntrySubGraph>> validCaseEntryToDominatedNodesMap = GetValidCases(dominatorTree, switchBlock);

            List<CaseLogicalConstruct> orderedCaseConstructs = new List<CaseLogicalConstruct>();
            PairList<List<int>, CFGBlockLogicalConstruct> labelsToCFGSuccessorsList = new PairList<List<int>, CFGBlockLogicalConstruct>();
            foreach (KeyValuePair<CFGBlockLogicalConstruct, List<int>> cfgSuccessorToLabelsPair in cfgSuccessorToLabelsMap)
            {
                ILogicalConstruct successor;
                HashSet<ISingleEntrySubGraph> dominatedNodes;
                if (LogicalFlowUtilities.TryGetParentConstructWithGivenParent(cfgSuccessorToLabelsPair.Key, parentConstruct, out successor) &&
                    validCaseEntryToDominatedNodesMap.TryGetValue(successor, out dominatedNodes))
                {
                    CaseLogicalConstruct newCaseConstruct = new CaseLogicalConstruct(successor);
                    newCaseConstruct.CaseNumbers.AddRange(cfgSuccessorToLabelsPair.Value);
                    newCaseConstruct.Body.UnionWith(dominatedNodes.Cast<ILogicalConstruct>());
                    newCaseConstruct.AttachCaseConstructToGraph();
                    orderedCaseConstructs.Add(newCaseConstruct);
                }
                else
                {
                    labelsToCFGSuccessorsList.Add(cfgSuccessorToLabelsPair.Value, cfgSuccessorToLabelsPair.Key);
                }
            }

            CaseLogicalConstruct defaultCase = null;
            CFGBlockLogicalConstruct defaultCFGSuccessor = GetCFGLogicalConstructFromBlock(switchData.DefaultCase);
            ILogicalConstruct defaultSuccessor;
            HashSet<ISingleEntrySubGraph> defaultCaseNodes;
            if (LogicalFlowUtilities.TryGetParentConstructWithGivenParent(defaultCFGSuccessor, parentConstruct, out defaultSuccessor) &&
                    validCaseEntryToDominatedNodesMap.TryGetValue(defaultSuccessor, out defaultCaseNodes))
            {
                defaultCase = new CaseLogicalConstruct(defaultSuccessor);
                if (HasSuccessors(defaultCaseNodes))
                {
                    defaultCase.Body.UnionWith(defaultCaseNodes.Cast<ILogicalConstruct>());
                }
                defaultCase.AttachCaseConstructToGraph();
            }

            SwitchLogicalConstruct theSwitch = SwitchLogicalConstruct.GroupInSwitchConstruct(switchBlock, orderedCaseConstructs, labelsToCFGSuccessorsList, defaultCase, defaultCFGSuccessor);
            UpdateDominatorTree(dominatorTree, theSwitch);
        }
 private void CreateSwitchConstruct(CFGBlockLogicalConstruct switchBlock, ILogicalConstruct parentConstruct, SwitchData switchData, DominatorTree dominatorTree)
 {
     stackVariable2 = this.GetOrderedCFGSuccessorToLabelsMap(switchData);
     V_0            = this.GetValidCases(dominatorTree, switchBlock);
     V_1            = new List <CaseLogicalConstruct>();
     V_2            = new PairList <List <int>, CFGBlockLogicalConstruct>();
     V_8            = stackVariable2.GetEnumerator();
     try
     {
         while (V_8.MoveNext())
         {
             V_9 = V_8.get_Current();
             if (!LogicalFlowUtilities.TryGetParentConstructWithGivenParent(V_9.get_Key(), parentConstruct, out V_10) || !V_0.TryGetValue(V_10, out V_11))
             {
                 V_2.Add(V_9.get_Value(), V_9.get_Key());
             }
             else
             {
                 V_12 = new CaseLogicalConstruct(V_10);
                 V_12.get_CaseNumbers().AddRange(V_9.get_Value());
                 V_12.get_Body().UnionWith(V_11.Cast <ILogicalConstruct>());
                 V_12.AttachCaseConstructToGraph();
                 V_1.Add(V_12);
             }
         }
     }
     finally
     {
         ((IDisposable)V_8).Dispose();
     }
     V_3 = null;
     V_4 = this.GetCFGLogicalConstructFromBlock(switchData.get_DefaultCase());
     if (LogicalFlowUtilities.TryGetParentConstructWithGivenParent(V_4, parentConstruct, out V_5) && V_0.TryGetValue(V_5, out V_6))
     {
         V_3 = new CaseLogicalConstruct(V_5);
         if (this.HasSuccessors(V_6))
         {
             V_3.get_Body().UnionWith(V_6.Cast <ILogicalConstruct>());
         }
         V_3.AttachCaseConstructToGraph();
     }
     V_7 = SwitchLogicalConstruct.GroupInSwitchConstruct(switchBlock, V_1, V_2, V_3, V_4);
     this.UpdateDominatorTree(dominatorTree, V_7);
     return;
 }
 private ILogicalConstruct FindChildBlockBelongsTo(ILogicalConstruct parent, CFGBlockLogicalConstruct block)
 {
     V_0 = null;
     V_1 = block;
     do
     {
         if (V_1.get_Parent() != parent)
         {
             V_1 = (ILogicalConstruct)V_1.get_Parent();
         }
         else
         {
             V_0 = V_1;
             break;
         }
     }while (V_1.get_Parent() != null);
     return(V_0);
 }
        /// <summary>
        /// Removes back edges from switch blocks. Switch cases can not form a loop. If the control flow forms a loop, it should be represented by goto-label contructs.
        /// </summary>
        /// <param name="theConstruct">The construct, that might contain switches.</param>
        private void RemoveBackEdgesFromSwitchConstructs(ILogicalConstruct theConstruct)
        {
            DFSTree dfsTree = DFSTBuilder.BuildTree(theConstruct);

            foreach (DFSTEdge edge in dfsTree.BackEdges)
            {
                ILogicalConstruct startConstruct = edge.Start.Construct as ILogicalConstruct;
                if (startConstruct is ConditionLogicalConstruct)
                {
                    continue;
                }

                CFGBlockLogicalConstruct startCfgConstruct = startConstruct as CFGBlockLogicalConstruct;
                if ((startCfgConstruct != null && startCfgConstruct.TheBlock.Last.OpCode.Code == Mono.Cecil.Cil.Code.Switch))
                {
                    MarkAsGotoEdge(startConstruct, edge.End.Construct as ILogicalConstruct);
                }
            }
        }
        private SwitchLogicalConstruct(CFGBlockLogicalConstruct entry, ICollection <CaseLogicalConstruct> body,
                                       PairList <List <int>, CFGBlockLogicalConstruct> nonDominatedCFGSuccessors, CaseLogicalConstruct defaultCase,
                                       CFGBlockLogicalConstruct defaultCFGSuccessor)
        {
            this.SwitchConditionExpression = entry.LogicalConstructExpressions[0];
            this.DefaultCase               = defaultCase;
            this.DefaultCFGSuccessor       = defaultCFGSuccessor;
            this.NonDominatedCFGSuccessors = nonDominatedCFGSuccessors;

            FillCasesArray(body);

            this.Entry = entry;
            RedirectChildrenToNewParent(GetBodyCollection());

            if (entry.CFGSuccessors.Contains(entry))
            {
                this.AddToPredecessors(entry);
                this.AddToSuccessors(entry);
            }
        }
        private SwitchLogicalConstruct(CFGBlockLogicalConstruct entry, ICollection<CaseLogicalConstruct> body,
            PairList<List<int>, CFGBlockLogicalConstruct> nonDominatedCFGSuccessors, CaseLogicalConstruct defaultCase,
            CFGBlockLogicalConstruct defaultCFGSuccessor)
	    {
            this.SwitchConditionExpression = entry.LogicalConstructExpressions[0];
            this.DefaultCase = defaultCase;
            this.DefaultCFGSuccessor = defaultCFGSuccessor;
            this.NonDominatedCFGSuccessors = nonDominatedCFGSuccessors;

            FillCasesArray(body);

            this.Entry = entry;
            RedirectChildrenToNewParent(GetBodyCollection());

            if (entry.CFGSuccessors.Contains(entry))
            {
                this.AddToPredecessors(entry);
                this.AddToSuccessors(entry);
            }
	    }
        /// <summary>
        /// Sets the true and false CFG successors of the construct.
        /// </summary>
        /// <param name="cfgConditionBlock"></param>
        private void SetTrueAndFalseSuccessors(CFGBlockLogicalConstruct cfgConditionBlock)
        {
            InstructionBlock block = cfgConditionBlock.TheBlock;

            //The successor at the last index is the near successor (by design). The ExpressionDecompilerStep ensures that the far successor will be
            //the true successor and the near successor will be the false successor.
            InstructionBlock trueSuccessorBlock  = block.Successors[0]; //The far successor
            InstructionBlock falseSuccessorBlock = block.Successors[1]; //The near successor

            foreach (CFGBlockLogicalConstruct cfgSuccessor in cfgConditionBlock.CFGSuccessors)
            {
                if (cfgSuccessor.TheBlock == trueSuccessorBlock)
                {
                    this.TrueCFGSuccessor = cfgSuccessor;
                }
                if (cfgSuccessor.TheBlock == falseSuccessorBlock)
                {
                    this.FalseCFGSuccessor = cfgSuccessor;
                }
            }
        }
 private bool CanBePartOfComplexCondition(ILogicalConstruct node, HashSet <ILogicalConstruct> nodesInCondition, CFGBlockLogicalConstruct commonSuccessor)
 {
     if (node == null || node as ConditionLogicalConstruct == null || !this.ArePredecessorsLegal(node, nodesInCondition) || !node.get_CFGSuccessors().Contains(commonSuccessor))
     {
         return(false);
     }
     return(!nodesInCondition.Contains(node));
 }
 public static SwitchLogicalConstruct GroupInSwitchConstruct(CFGBlockLogicalConstruct entry, ICollection<CaseLogicalConstruct> body,
     PairList<List<int>, CFGBlockLogicalConstruct> nonDominatedCFGSuccessors, CaseLogicalConstruct defaultCase,
     CFGBlockLogicalConstruct defaultCFGSuccessor)
 {
     return new SwitchLogicalConstruct(entry, body, nonDominatedCFGSuccessors, defaultCase, defaultCFGSuccessor);
 }
        /// <summary>
        /// Sets the true and false CFG successors of the construct.
        /// </summary>
        /// <param name="cfgConditionBlock"></param>
        private void SetTrueAndFalseSuccessors(CFGBlockLogicalConstruct cfgConditionBlock)
        {
            InstructionBlock block = cfgConditionBlock.TheBlock;

            //The successor at the last index is the near successor (by design). The ExpressionDecompilerStep ensures that the far successor will be
            //the true successor and the near successor will be the false successor.
            InstructionBlock trueSuccessorBlock = block.Successors[0]; //The far successor
            InstructionBlock falseSuccessorBlock = block.Successors[1]; //The near successor

            foreach (CFGBlockLogicalConstruct cfgSuccessor in cfgConditionBlock.CFGSuccessors)
            {
                if(cfgSuccessor.TheBlock == trueSuccessorBlock)
                {
                    this.TrueCFGSuccessor = cfgSuccessor;
                }
                if(cfgSuccessor.TheBlock == falseSuccessorBlock)
                {
                    this.FalseCFGSuccessor = cfgSuccessor;
                }
            }
        }
        /// <summary>
        /// Changes the successors of the given instruction block to reflect the changes in the logical tree.
        /// </summary>
        /// <remarks>
        /// Also modifies switch data.
        /// Done because later substeps of the LogicalFlowBuilderStep depend on the successor information of the CFG
        /// (e.g. Determining the true and false successors of a ConditionLogicalConstruct, determining the cases of a switch/NWayConditional construct).
        /// </remarks>
        /// <param name="theCFGConstruct"></param>
        /// <param name="theCFGSuccessor"></param>
        private void ProcessMultiWayCFGPredecessor(CFGBlockLogicalConstruct finallyBody, InstructionBlock theBlock, InstructionBlock theNewSuccessor)
        {
            InstructionBlock theFinallyBlock = finallyBody.TheBlock;

            for (int i = 0; i < theBlock.Successors.Length; i++)
            {
                if (theBlock.Successors[i] == theFinallyBlock)
                {
                    theBlock.Successors[i] = theNewSuccessor;
                }
            }

            SwitchData switchData;
            if(methodContext.ControlFlowGraph.SwitchBlocksInformation.TryGetValue(theBlock, out switchData))
            {
                InstructionBlock[] theConditionCases = switchData.OrderedCasesArray;
                for (int i = 0; i < theConditionCases.Length; i++)
                {
                    if (theConditionCases[i] == theFinallyBlock)
                    {
                        theConditionCases[i] = theNewSuccessor;
                    }
                }

                if (switchData.DefaultCase == theFinallyBlock)
                {
                    switchData.DefaultCase = theNewSuccessor;
                }
            }
        }
 public static SwitchLogicalConstruct GroupInSwitchConstruct(CFGBlockLogicalConstruct entry, ICollection <CaseLogicalConstruct> body, PairList <List <int>, CFGBlockLogicalConstruct> nonDominatedCFGSuccessors, CaseLogicalConstruct defaultCase, CFGBlockLogicalConstruct defaultCFGSuccessor)
 {
     return(new SwitchLogicalConstruct(entry, body, nonDominatedCFGSuccessors, defaultCase, defaultCFGSuccessor));
 }
 /// <summary>
 /// Determines whether the specified node can be added in a complex condition.
 /// </summary>
 /// <param name="node">The node that we want to add to the condition.</param>
 /// <param name="nodesInCondition">The nodes that are in the complex condition.</param>
 /// <param name="commonSuccessor">The supposed common successor.</param>
 /// <returns></returns>
 private bool CanBePartOfComplexCondition(ILogicalConstruct node, HashSet<ILogicalConstruct> nodesInCondition, CFGBlockLogicalConstruct commonSuccessor)
 {
     //In order to add the node to the condition it has to be a condition node. All of it's predecessors should be in the complex condition.
     //The node should have for successor the supposed common successor (the check is optimized). And the node should not be part of the complex
     //condition.
     return node != null && node is ConditionLogicalConstruct && ArePredecessorsLegal(node, nodesInCondition) 
         && node.CFGSuccessors.Contains(commonSuccessor) && !nodesInCondition.Contains(node);
 }
        /// <summary>
        /// Generates the try/finally construct that is represented by the specifed exception handler info and attaches it to the logical tree.
        /// </summary>
        /// <param name="handlerInfo"></param>
        private void GenerateTryFinallyHandler(YieldExceptionHandlerInfo handlerInfo)
        {
            finallyBlocks = new HashSet<ILogicalConstruct>();

            entryOfTry = GetStateBeginBlockConstruct(handlerInfo.TryBeginState);

            BuildTryBody(handlerInfo);

            BlockLogicalConstruct newFinally;
            if (handlerInfo.HandlerType == YieldExceptionHandlerType.Method)
            {
                if (newFinallyBody == null)
                {
                    throw new Exception("Could not determine the end ot the try block");
                }

                RemoveExcessNodesFromTheTryBlock();

                ProcessFinallyNodes();

                newFinally = new BlockLogicalConstruct(newFinallyBody, new ILogicalConstruct[] { newFinallyBody });
            }
            else
            {
                newFinally = GenerateFinallyBlock();
            }

            BlockLogicalConstruct newTry = new BlockLogicalConstruct(entryOfTry, newTryBody);
            TryFinallyLogicalConstruct newTryFinallyConstruct = new TryFinallyLogicalConstruct(newTry, newFinally);

            createdConstructsToIntervalMap[newTryFinallyConstruct] = handlerInfo;

            CleanUpOrderedNodes(newTryFinallyConstruct);
        }
        private void DetachFromLogicalTree(CFGBlockLogicalConstruct node)
        {
            if(node.CFGPredecessors.Count > 0 || node.CFGSuccessors.Count > 0)
            {
                throw new Exception("This node cannot be detached from the logical tree.");
            }

            node.Parent.Children.Remove(node);
            CFGBlockLogicalConstruct[] cfgConstructsArray = logicalContext.CFGBlockToLogicalConstructMap[node.TheBlock];

            if(cfgConstructsArray.Length == 1)
            {
                if(cfgConstructsArray[0] != node)
                {
                    throw new Exception("Logical tree is inconsistent.");
                }

                logicalContext.CFGBlockToLogicalConstructMap.Remove(node.TheBlock);
            }

            CFGBlockLogicalConstruct[] newCFGConstructsArray = new CFGBlockLogicalConstruct[cfgConstructsArray.Length - 1];
            for (int i = 0 , j = 0; i < cfgConstructsArray.Length; i++, j++)
            {
                if(cfgConstructsArray[i] == node)
                {
                    --j;
                    continue;
                }

                if(j == cfgConstructsArray.Length)
                {
                    throw new Exception("Logical tree is inconsistent.");
                }

                newCFGConstructsArray[j] = cfgConstructsArray[i];
            }

            logicalContext.CFGBlockToLogicalConstructMap[node.TheBlock] = newCFGConstructsArray;
        }
        /// <summary>
        /// Checks each a node before adding its successors to the <paramref name="bfsQueue"/>.
        /// </summary>
        /// <remarks>
        /// If the node is a CFGBlockLC and it contains the invocation of the finally method, or the entry of the finally block,
        /// then we should not continue the traversal.
        /// </remarks>
        /// <param name="handlerInfo"></param>
        /// <param name="bfsQueue"></param>
        /// <param name="currentNode"></param>
        private void ProcessCurrentNode(YieldExceptionHandlerInfo handlerInfo, Queue<ILogicalConstruct> bfsQueue, ILogicalConstruct currentNode)
        {
            if(currentNode is CFGBlockLogicalConstruct)
            {
                CFGBlockLogicalConstruct currentCFGNode = currentNode as CFGBlockLogicalConstruct;
                for (int i = 0; i < currentCFGNode.LogicalConstructExpressions.Count; i++)
                {
                    Expression currentExpression = currentCFGNode.LogicalConstructExpressions[i];

                    int value;
                    if(TryGetStateAssignValue(currentExpression, out value))
                    {
                        if(value < handlerInfo.TryBeginState || value > handlerInfo.TryEndState) //sanity check
                        {
                            if(handlerInfo.HandlerType != YieldExceptionHandlerType.Method &&
                                TryProcessConditionalDisposeHandler(handlerInfo, currentCFGNode))
                            {
                                return;
                            }
                            throw new Exception("Invalid state value");
                        }
                    }
                    else if(handlerInfo.HandlerType == YieldExceptionHandlerType.Method &&
                        currentExpression.CodeNodeType == CodeNodeType.MethodInvocationExpression &&
                        (currentExpression as MethodInvocationExpression).MethodExpression.MethodDefinition == handlerInfo.FinallyMethodDefinition)
                    {
                        //For the finally block we need the CFGBlockLC that contains only the invocation of the finally method.
                        //That's why we need to split the CFGBlockLC, if there are other expressions besides the invocation.
                        CFGBlockLogicalConstruct currentFinallyBlock;
                        if (currentCFGNode.LogicalConstructExpressions.Count == 1)
                        {
                            if(newFinallyBody == null)
                            {
                                newFinallyBody = currentCFGNode;
                            }
                            finallyBlocks.Add(newFinallyBody);
                            orderedCFGNodes.Remove(currentCFGNode);
                            return;
                        }

                        if (i == 0)
                        {
                            KeyValuePair<CFGBlockLogicalConstruct, CFGBlockLogicalConstruct> newConstructsPair =
                                LogicalFlowUtilities.SplitCFGBlockAt(logicalContext, currentCFGNode, i + 1);

                            currentFinallyBlock = newConstructsPair.Key;
                            orderedCFGNodes[orderedCFGNodes.IndexOf(currentCFGNode)] = newConstructsPair.Value;
                        }
                        else if (i < currentCFGNode.LogicalConstructExpressions.Count - 1)
                        {
                            KeyValuePair<CFGBlockLogicalConstruct, CFGBlockLogicalConstruct> endOfTryPair =
                                LogicalFlowUtilities.SplitCFGBlockAt(logicalContext, currentCFGNode, i);
                            newTryBody.Add(endOfTryPair.Key);

                            KeyValuePair<CFGBlockLogicalConstruct, CFGBlockLogicalConstruct> finallyRestOfBlockPair =
                                LogicalFlowUtilities.SplitCFGBlockAt(logicalContext, endOfTryPair.Value, 1);

                            currentFinallyBlock = finallyRestOfBlockPair.Key;
                            orderedCFGNodes[orderedCFGNodes.IndexOf(currentCFGNode)] = finallyRestOfBlockPair.Value;
                        }
                        else // i == count - 1
                        {
                            KeyValuePair<CFGBlockLogicalConstruct, CFGBlockLogicalConstruct> tryFinallyPair =
                                LogicalFlowUtilities.SplitCFGBlockAt(logicalContext, currentCFGNode, i);

                            newTryBody.Add(tryFinallyPair.Key);
                            currentFinallyBlock = tryFinallyPair.Value;

                            orderedCFGNodes.Remove(currentCFGNode);
                        }

                        if(newFinallyBody == null)
                        {
                            newFinallyBody = currentFinallyBlock;
                        }
                        finallyBlocks.Add(currentFinallyBlock);

                        return;
                    }
                }
            }
            else if(currentNode is TryFinallyLogicalConstruct)
            {
                TryFinallyLogicalConstruct tryFinallyConstruct = currentNode as TryFinallyLogicalConstruct;
                YieldExceptionHandlerInfo oldHandlerInfo;
                if(createdConstructsToIntervalMap.TryGetValue(tryFinallyConstruct, out oldHandlerInfo) &&
                    (oldHandlerInfo.TryBeginState < handlerInfo.TryBeginState || oldHandlerInfo.TryEndState > handlerInfo.TryEndState))
                {
                    throw new Exception("This try/finally construct cannot be nested in the current construct");
                }
            }

            newTryBody.Add(currentNode);
            foreach (ILogicalConstruct successor in currentNode.SameParentSuccessors)
            {
                bfsQueue.Enqueue(successor);
            }
        }
 /// <summary>
 /// Redirect the predecessors and successors of the finally node.
 /// </summary>
 /// <remarks>
 /// Check if the finally node is only reachable by nodes in the try block.
 /// Make the successor of the finally node successor to all of the predecessors of the finally node.
 /// This will detach the finally node from the subgraph, which is a desired result since every normal finally block is not reachable from any where
 /// (the CLR takes care of executing the code in the finally block).
 /// </remarks>
 /// <param name="finallyCFGBlock"></param>
 private void ProcessFinallyNode(CFGBlockLogicalConstruct finallyCFGBlock)
 {
     ProcessFinallyNode(finallyCFGBlock, finallyCFGBlock);
 }
        /// <summary>
        /// Redirect the predecessors and successors of the finally block.
        /// </summary>
        /// <remarks>
        /// Check if the finallyBlockEntry is only reachable by nodes in the try block.
        /// Make the successor of the finallyBlockEnd successor to all of the predecessors of the finallyBlockEntry.
        /// This will detach the finally block from the subgraph, which is a desired result since every normal finally block is not reachable from any where
        /// (the CLR takes care of executing the code in the finally block).
        /// </remarks>
        /// <param name="finallyBlockEntry"></param>
        /// <param name="finallyBlockEnd"></param>
        /// <returns>The successor of the finally block.</returns>
        private CFGBlockLogicalConstruct ProcessFinallyNode(CFGBlockLogicalConstruct finallyBlockEntry, CFGBlockLogicalConstruct finallyBlockEnd)
        {
            foreach (ILogicalConstruct predecessor in finallyBlockEntry.SameParentPredecessors)
            {
                if (!newTryBody.Contains(predecessor))
                {
                    throw new Exception("Invalid entry to the finally block");
                }
            }

            CFGBlockLogicalConstruct finallySuccessor;
            using (IEnumerator<CFGBlockLogicalConstruct> enumerator = finallyBlockEnd.CFGSuccessors.GetEnumerator())
            {
                enumerator.MoveNext();
                finallySuccessor = enumerator.Current;

                if (enumerator.MoveNext())
                {
                    throw new Exception("Invalid count of successors");
                }
            }

            HashSet<CFGBlockLogicalConstruct> finallyCFGPredecessors = new HashSet<CFGBlockLogicalConstruct>(finallyBlockEntry.CFGPredecessors);
            foreach (CFGBlockLogicalConstruct cfgPredecessor in finallyCFGPredecessors)
            {
                if (cfgPredecessor.TheBlock != finallyBlockEntry.TheBlock && cfgPredecessor.TheBlock.Successors.Length > 1)
                {
                    ProcessMultiWayCFGPredecessor(finallyBlockEntry, cfgPredecessor.TheBlock, finallySuccessor.TheBlock);
                }

                LogicalConstructBase currenConstruct = cfgPredecessor;
                while (currenConstruct != finallyBlockEntry.Parent)
                {
                    currenConstruct.RemoveFromSuccessors(finallyBlockEntry);
                    currenConstruct.AddToSuccessors(finallySuccessor);

                    currenConstruct = currenConstruct.Parent as LogicalConstructBase;
                }

                finallySuccessor.AddToPredecessors(cfgPredecessor);
                finallyBlockEntry.RemoveFromPredecessors(cfgPredecessor);
            }

            finallySuccessor.RemoveFromPredecessors(finallyBlockEnd);
            finallyBlockEnd.RemoveFromSuccessors(finallySuccessor);

            return finallySuccessor;
        }
 /// <summary>
 /// Creates a condition construct from the specified CFG construct and inserts it to the logical tree.
 /// </summary>
 /// <param name="cfgConditionBlock"></param>
 /// <returns>The created condition construct.</returns>
 public static ConditionLogicalConstruct GroupInSimpleConditionConstruct(CFGBlockLogicalConstruct cfgConditionBlock)
 {
     return(new ConditionLogicalConstruct(cfgConditionBlock));
 }
 /// <summary>
 /// Determines whether the specified node can be added in a complex condition.
 /// </summary>
 /// <param name="node">The node that we want to add to the condition.</param>
 /// <param name="nodesInCondition">The nodes that are in the complex condition.</param>
 /// <param name="commonSuccessor">The supposed common successor.</param>
 /// <returns></returns>
 private bool CanBePartOfComplexCondition(ILogicalConstruct node, HashSet <ILogicalConstruct> nodesInCondition, CFGBlockLogicalConstruct commonSuccessor)
 {
     //In order to add the node to the condition it has to be a condition node. All of it's predecessors should be in the complex condition.
     //The node should have for successor the supposed common successor (the check is optimized). And the node should not be part of the complex
     //condition.
     return(node != null && node is ConditionLogicalConstruct && ArePredecessorsLegal(node, nodesInCondition) &&
            node.CFGSuccessors.Contains(commonSuccessor) && !nodesInCondition.Contains(node));
 }
 public PartialCFGBlockLogicalConstruct(CFGBlockLogicalConstruct originalCFGConstruct, IEnumerable<Expression> expressions)
 :base(originalCFGConstruct.TheBlock, expressions)
 {
     OriginalCFGConstruct = originalCFGConstruct;
     RedirectParent();
 }
        /// <summary>
        /// Splits the given CFG construct into two partial constructs. The first containing the expressions with indices 0 to expressionIndex - 1, the second -
        /// expressionIndex to end. This method modifies the logicalContext.CFGBlockToLogicalConstructMap
        /// </summary>
        /// <param name="logicalContext"></param>
        /// <param name="cfgBlock"></param>
        /// <param name="expressionIndex"></param>
        /// <returns>A key value pair containing the first partial construct as key and the second as value.</returns>
        public static KeyValuePair<CFGBlockLogicalConstruct, CFGBlockLogicalConstruct> SplitCFGBlockAt(LogicalFlowBuilderContext logicalContext,
            CFGBlockLogicalConstruct cfgBlock, int expressionIndex)
        {
            List<Expression> blockExpressions = cfgBlock.LogicalConstructExpressions;

            if(blockExpressions == null)
            {
                throw new ArgumentNullException("blockExpressions");
            }

            if(expressionIndex <= 0 || expressionIndex >= blockExpressions.Count)
            {
                throw new ArgumentOutOfRangeException("expressionIndex");
            }

            CFGBlockLogicalConstruct[] instructionBlockConstructs = logicalContext.CFGBlockToLogicalConstructMap[cfgBlock.TheBlock];
            int cfgBlockArrayLength = instructionBlockConstructs.Length;

            int cfgBlockIndex;
            for (cfgBlockIndex = 0; cfgBlockIndex < cfgBlockArrayLength; cfgBlockIndex++)
            {
                if(cfgBlock == instructionBlockConstructs[cfgBlockIndex])
                {
                    break;
                }
            }

            if(cfgBlockIndex == cfgBlockArrayLength)
            {
                throw new ArgumentException("cfgBlock");
            }

            List<Expression> firstExpressionsList = cfgBlock.LogicalConstructExpressions.GetRange(0, expressionIndex);
            PartialCFGBlockLogicalConstruct firstPartial = new PartialCFGBlockLogicalConstruct(cfgBlock, firstExpressionsList);
            firstPartial.RedirectPredecessors();

            List<Expression> secondExpressionsList = cfgBlock.LogicalConstructExpressions.GetRange(expressionIndex, blockExpressions.Count - expressionIndex);
            PartialCFGBlockLogicalConstruct secondPartial = new PartialCFGBlockLogicalConstruct(cfgBlock, secondExpressionsList);
            secondPartial.RedirectSuccessors();

            firstPartial.AddToSuccessors(secondPartial);
            secondPartial.AddToPredecessors(firstPartial);

            CFGBlockLogicalConstruct[] updatedCollection = new CFGBlockLogicalConstruct[cfgBlockArrayLength + 1];
            for (int i = 0, j = 0; i < cfgBlockArrayLength; i++, j++)
            {
                if (i != cfgBlockIndex)
                {
                    updatedCollection[j] = instructionBlockConstructs[i];
                }
                else
                {
                    updatedCollection[j] = firstPartial;
                    updatedCollection[++j] = secondPartial;
                }
            }

            logicalContext.CFGBlockToLogicalConstructMap[cfgBlock.TheBlock] = updatedCollection;

            return new KeyValuePair<CFGBlockLogicalConstruct, CFGBlockLogicalConstruct>(firstPartial, secondPartial);
        }
		ILogicalConstruct FindChildBlockBelongsTo(ILogicalConstruct parent, CFGBlockLogicalConstruct block)
		{
			ILogicalConstruct result = null, current = block;

			do
			{
				if (current.Parent == parent)
				{
					result = current;
					break;
				}

				current = (ILogicalConstruct)current.Parent;

			} while (current.Parent != null);

			return result;
		}
        /// <summary>
        /// Builds the try body of the specified exception handler starting from the given entry node.
        /// </summary>
        /// <remarks>
        /// We assume that all nodes before reaching the finally block are in the try construct.
        /// </remarks>
        /// <param name="handlerInfo"></param>
        /// <param name="entryOfTry"></param>
        private void BuildTryBody(YieldExceptionHandlerInfo handlerInfo)
        {
            newTryBody = new HashSet<ILogicalConstruct>();
            newTryBody.Add(entryOfTry);
            newFinallyBody = null;

            HashSet<ILogicalConstruct> traversedNodes = new HashSet<ILogicalConstruct>();
            Queue<ILogicalConstruct> bfsQueue = new Queue<ILogicalConstruct>();
            foreach (ILogicalConstruct successor in entryOfTry.SameParentSuccessors)
            {
                bfsQueue.Enqueue(successor);
            }

            while (bfsQueue.Count > 0)
            {
                ILogicalConstruct currentNode = bfsQueue.Dequeue();
                if (!traversedNodes.Add(currentNode) || finallyBlocks.Contains(currentNode))
                {
                    continue;
                }

                ProcessCurrentNode(handlerInfo, bfsQueue, currentNode);
            }
        }
 /// <summary>
 /// If the given successor is the entry of the condition we update the predecessor and successor collections of the condition.
 /// </summary>
 /// <param name="cfgSuccessor"></param>
 private void ManageSuccessorInCaseOfLoop(CFGBlockLogicalConstruct cfgSuccessor)
 {
     if(this.FirstBlock == cfgSuccessor)
     {
         this.AddToSuccessors(cfgSuccessor);
         foreach (CFGBlockLogicalConstruct cfgChild in this.Children)
         {
             if(cfgChild.CFGSuccessors.Contains(cfgSuccessor))
             {
                 this.AddToPredecessors(cfgChild);
             }
         }
     }
 }
        internal static CFGBlockLogicalConstruct FindGuardedBlockCFGFollowNode(ExceptionHandlingLogicalConstruct construct, HashSet <CFGBlockLogicalConstruct> outOfconsideration)
        {
            //TODO: Don't consider leaves to blocks that end with return. The return can simpy be copied to the place where the leave originates by
            // the statement decompielr or the goto elimination later.


            //find all the targets the try/catch/filter/fault/finally blocks in the construct jump/leave to
            //record the number of leaves to each target
            Dictionary <CFGBlockLogicalConstruct, uint> numberOfHandlersLeavingToBlock = new Dictionary <CFGBlockLogicalConstruct, uint>();

            AddSuccessorsToCount(construct.Try, numberOfHandlersLeavingToBlock);
            uint leavableConstructsCount = 1;

            if (construct is TryCatchFilterLogicalConstruct)
            {
                TryCatchFilterLogicalConstruct tcf = construct as TryCatchFilterLogicalConstruct;
                foreach (IFilteringExceptionHandler handler in tcf.Handlers)
                {
                    AddSuccessorsToCount(handler, numberOfHandlersLeavingToBlock);
                    leavableConstructsCount++;
                }
            }
            else if (construct is TryFaultLogicalConstruct)
            {
                AddSuccessorsToCount((construct as TryFaultLogicalConstruct).Fault, numberOfHandlersLeavingToBlock);
                leavableConstructsCount++;
            }
            else if (construct is TryFinallyLogicalConstruct)
            {
                AddSuccessorsToCount((construct as TryFinallyLogicalConstruct).Finally, numberOfHandlersLeavingToBlock);
                leavableConstructsCount++;
            }

            //remove the leave targets taht should nto be considered
            foreach (CFGBlockLogicalConstruct ooc in outOfconsideration)
            {
                if (numberOfHandlersLeavingToBlock.ContainsKey(ooc))
                {
                    numberOfHandlersLeavingToBlock.Remove(ooc);
                }
            }

            if (numberOfHandlersLeavingToBlock.Count == 0)
            {
                return(null);
            }

            //find the leave targets that greatest number of exception handling blocks (try/catch/filter/fault/finally) jump to
            HashSet <CFGBlockLogicalConstruct> mostBlocksExitTo  = new HashSet <CFGBlockLogicalConstruct>();
            CFGBlockLogicalConstruct           randomLeaveTarget = numberOfHandlersLeavingToBlock.Keys.FirstOrDefault <CFGBlockLogicalConstruct>();

            mostBlocksExitTo.Add(randomLeaveTarget);
            uint maxNumberOfLeaveTargetPredecessors = numberOfHandlersLeavingToBlock[randomLeaveTarget];

            foreach (CFGBlockLogicalConstruct leaveTarget in numberOfHandlersLeavingToBlock.Keys)
            {
                if (numberOfHandlersLeavingToBlock[leaveTarget] > maxNumberOfLeaveTargetPredecessors)
                {
                    maxNumberOfLeaveTargetPredecessors = numberOfHandlersLeavingToBlock[leaveTarget];
                    mostBlocksExitTo.Clear();
                    mostBlocksExitTo.Add(leaveTarget);
                }
                else if (numberOfHandlersLeavingToBlock[leaveTarget] == maxNumberOfLeaveTargetPredecessors)
                {
                    mostBlocksExitTo.Add(leaveTarget);
                }
            }

            //use various heuristics to determine the best follow node
            //the follow node that will result in the smallest number of gotos is considered superior
            //the follow node could be changed once loops are created if it turns out loop condition was chosen as a follow node (i.e. we chose a continue edge)
            if (mostBlocksExitTo.Count == 1)
            {
                return(mostBlocksExitTo.FirstOrDefault <CFGBlockLogicalConstruct>());
            }
            else
            {
                HashSet <CFGBlockLogicalConstruct> mostLeavesPointTo = new HashSet <CFGBlockLogicalConstruct>();
                uint maxLeavesToSingleTarget = 0;
                foreach (CFGBlockLogicalConstruct leaveTarget in mostBlocksExitTo)
                {
                    uint leavesToThisTarget = 0;
                    HashSet <CFGBlockLogicalConstruct> constructCFGBlocks = construct.CFGBlocks;
                    foreach (CFGBlockLogicalConstruct leaveTargetpredecessor in leaveTarget.CFGPredecessors)
                    {
                        if (constructCFGBlocks.Contains(leaveTargetpredecessor))
                        {
                            leavesToThisTarget++;
                        }
                    }

                    if (leavesToThisTarget >= maxLeavesToSingleTarget)
                    {
                        if (leavesToThisTarget > maxLeavesToSingleTarget)
                        {
                            maxLeavesToSingleTarget = leavesToThisTarget;
                            mostLeavesPointTo.Clear();
                        }
                        mostLeavesPointTo.Add(leaveTarget);
                    }
                }

                //TODO: Try anoher heuristics here to chose the follow node that will minimize the number of gotos

                CFGBlockLogicalConstruct result = mostLeavesPointTo.FirstOrDefault <CFGBlockLogicalConstruct>();
                //HEURISTICS: Of all possible follow nodes we try to chose the one which start index is greater than the index of the exception construct start
                //but less than the start indexes of all other possible candidates. We rely on the assumption that the control flow closely resembles the ordering of
                // the IL instructions, i.e. if Instr. A  comes before Instr. B the chances are that Instr. A will have to be executed before Instr. B in any workflow.
                // That might not be the case but it's a good assumption since the compilers will try to express teh control flow in the least amount of jumps possible
                // for performance reasons.
                if (result.Index < construct.Entry.Index)
                {
                    CFGBlockLogicalConstruct closestAfterConstruct = null;
                    foreach (CFGBlockLogicalConstruct candidate in mostLeavesPointTo)
                    {
                        if (candidate.Index > construct.Entry.Index)
                        {
                            if (closestAfterConstruct != null && closestAfterConstruct.Index < candidate.Index)
                            {
                                continue;
                            }
                            closestAfterConstruct = candidate;
                        }
                    }

                    if (closestAfterConstruct != null)
                    {
                        result = closestAfterConstruct;
                    }
                }
                return(result);
            }
        }
 /// <summary>
 /// Creates a condition construct from the specified CFG construct and inserts it to the logical tree.
 /// </summary>
 /// <param name="cfgConditionBlock"></param>
 /// <returns>The created condition construct.</returns>
 public static ConditionLogicalConstruct GroupInSimpleConditionConstruct(CFGBlockLogicalConstruct cfgConditionBlock)
 {
     return new ConditionLogicalConstruct(cfgConditionBlock);
 }
        /// <summary>
        /// Determines whether or not there is a conditional dispose starting from this block.
        /// </summary>
        /// <remarks>
        /// Since the conditional dispose is the same as in the Dispose method, we are trying to find the same pattern.
        /// <code>
        /// this.stateField = nextState;
        /// (this.disposableField = this.enumeratorField as IDisposable;)   -- this might be missing
        /// if(this.disposableField != null)
        /// {
        ///     this.disposableField.Dispose();
        /// }
        /// </code>
        /// </remarks>
        /// <param name="yieldExceptionHandler"></param>
        /// <param name="startBlock"></param>
        /// <returns></returns>
        private bool TryProcessConditionalDisposeHandler(YieldExceptionHandlerInfo yieldExceptionHandler, CFGBlockLogicalConstruct startBlock)
        {
            if(finallyBlocks.Count > 0)
            {
                return false;
            }

            if(!(startBlock is PartialCFGBlockLogicalConstruct) || startBlock.CFGSuccessors.Count != 1)
            {
                return false;
            }

            if(startBlock.LogicalConstructExpressions.Count == 0)
            {
                return false;
            }

            BinaryExpression stateAssignExpression = startBlock.LogicalConstructExpressions[0] as BinaryExpression;
            if(stateAssignExpression == null || !stateAssignExpression.IsAssignmentExpression ||
                stateAssignExpression.Left.CodeNodeType != CodeNodeType.FieldReferenceExpression ||
                (stateAssignExpression.Left as FieldReferenceExpression).Field.Resolve() != stateFieldRef ||
                stateAssignExpression.Right.CodeNodeType != CodeNodeType.LiteralExpression ||
                (int)((stateAssignExpression.Right as LiteralExpression).Value) != yieldExceptionHandler.NextState)
            {
                return false;
            }

            if(startBlock.LogicalConstructExpressions.Count == 2 && yieldExceptionHandler.HandlerType == YieldExceptionHandlerType.ConditionalDispose)
            {
                BinaryExpression disposableAssignExpression = startBlock.LogicalConstructExpressions[1] as BinaryExpression;
                if (disposableAssignExpression == null || !disposableAssignExpression.IsAssignmentExpression ||
                    disposableAssignExpression.Left.CodeNodeType != CodeNodeType.FieldReferenceExpression ||
                    (disposableAssignExpression.Left as FieldReferenceExpression).Field != yieldExceptionHandler.DisposableField ||
                    disposableAssignExpression.Right.CodeNodeType != CodeNodeType.SafeCastExpression ||
                    (disposableAssignExpression.Right as SafeCastExpression).Expression.CodeNodeType != CodeNodeType.FieldReferenceExpression ||
                    ((disposableAssignExpression.Right as SafeCastExpression).Expression as FieldReferenceExpression).Field != yieldExceptionHandler.EnumeratorField)
                {
                    return false;
                }
            }
            else if(startBlock.LogicalConstructExpressions.Count != 1 || yieldExceptionHandler.HandlerType != YieldExceptionHandlerType.SimpleConditionalDispose)
            {
                return false;
            }

            CFGBlockLogicalConstruct conditionBlock;
            IEnumerator<CFGBlockLogicalConstruct> enumerator = startBlock.CFGSuccessors.GetEnumerator();
            using(enumerator)
            {
                enumerator.MoveNext();
                conditionBlock = enumerator.Current;
            }

            if(conditionBlock.LogicalConstructExpressions.Count != 1)
            {
                return false;
            }

            BinaryExpression isNullCheckExpression = conditionBlock.LogicalConstructExpressions[0] as BinaryExpression;
            if(isNullCheckExpression == null || isNullCheckExpression.Operator != BinaryOperator.ValueEquality ||
                isNullCheckExpression.Left.CodeNodeType != CodeNodeType.FieldReferenceExpression ||
                (isNullCheckExpression.Left as FieldReferenceExpression).Field != yieldExceptionHandler.DisposableField ||
                isNullCheckExpression.Right.CodeNodeType != CodeNodeType.LiteralExpression ||
                (isNullCheckExpression.Right as LiteralExpression).Value != null)
            {
                return false;
            }

            CFGBlockLogicalConstruct disposeCallBlock = null;
            foreach (ILogicalConstruct successor in conditionBlock.CFGSuccessors)
            {
                CFGBlockLogicalConstruct cfgSuccessor = successor as CFGBlockLogicalConstruct;
                if(cfgSuccessor != null && cfgSuccessor.CFGPredecessors.Count == 1)
                {
                    disposeCallBlock = cfgSuccessor;
                    break;
                }
            }

            if(disposeCallBlock == null || disposeCallBlock.LogicalConstructExpressions.Count != 1)
            {
                return false;
            }

            MethodInvocationExpression disposeMethodInvocation = disposeCallBlock.LogicalConstructExpressions[0] as MethodInvocationExpression;
            if(disposeMethodInvocation == null || !disposeMethodInvocation.VirtualCall ||
                disposeMethodInvocation.MethodExpression.Target.CodeNodeType != CodeNodeType.FieldReferenceExpression ||
                (disposeMethodInvocation.MethodExpression.Target as FieldReferenceExpression).Field != yieldExceptionHandler.DisposableField ||
                disposeMethodInvocation.MethodExpression.Method.Name != "Dispose")
            {
                return false;
            }

            this.finallyEntryBlock = startBlock;
            finallyBlocks.Add(startBlock);

            this.conditionBlock = conditionBlock;
            finallyBlocks.Add(conditionBlock);

            this.disposeCallBlock = disposeCallBlock;
            finallyBlocks.Add(disposeCallBlock);

            return true;
        }