Пример #1
0
        ControlFlowNode[] PrepareReverseCFG(ControlFlowNode loopHead, bool treatBackEdgesAsExits)
        {
            ControlFlowNode[] cfg = context.ControlFlowGraph.cfg;
            ControlFlowNode[] rev = new ControlFlowNode[cfg.Length + 1];
            for (int i = 0; i < cfg.Length; i++)
            {
                rev[i] = new ControlFlowNode {
                    UserIndex = i, UserData = cfg[i].UserData
                };
            }
            ControlFlowNode exitNode = new ControlFlowNode {
                UserIndex = -1
            };

            rev[cfg.Length] = exitNode;
            for (int i = 0; i < cfg.Length; i++)
            {
                if (!loopHead.Dominates(cfg[i]))
                {
                    continue;
                }
                // Add reverse edges for all edges in cfg
                foreach (var succ in cfg[i].Successors)
                {
                    if (loopHead.Dominates(succ) && (!treatBackEdgesAsExits || loopHead != succ))
                    {
                        rev[succ.UserIndex].AddEdgeTo(rev[i]);
                    }
                    else
                    {
                        exitNode.AddEdgeTo(rev[i]);
                    }
                }
                if (context.ControlFlowGraph.HasDirectExitOutOfContainer(cfg[i]))
                {
                    exitNode.AddEdgeTo(rev[i]);
                }
            }
            Dominance.ComputeDominance(exitNode, context.CancellationToken);
            return(rev);
        }
Пример #2
0
        /// <summary>
        /// Constructs a new control flow graph.
        /// Each node cfg[i] has a corresponding node rev[i].
        /// Edges are only created for nodes dominated by loopHead, and are in reverse from their direction
        /// in the primary CFG.
        /// An artificial exit node is used for edges that leave the set of nodes dominated by loopHead,
        /// or that leave the block Container.
        /// </summary>
        /// <param name="loopHead">Entry point of the loop.</param>
        /// <param name="exitNodeArity">out: The number of different CFG nodes.
        /// Possible values:
        ///  0 = no CFG nodes used as exit nodes (although edges leaving the block container might still be exits);
        ///  1 = a single CFG node (not dominated by loopHead) was used as an exit node;
        ///  2 = more than one CFG node (not dominated by loopHead) was used as an exit node.
        /// </param>
        /// <returns></returns>
        ControlFlowNode[] PrepareReverseCFG(ControlFlowNode loopHead, out int exitNodeArity)
        {
            ControlFlowNode[] cfg = context.ControlFlowGraph.cfg;
            ControlFlowNode[] rev = new ControlFlowNode[cfg.Length + 1];
            for (int i = 0; i < cfg.Length; i++)
            {
                rev[i] = new ControlFlowNode {
                    UserIndex = i, UserData = cfg[i].UserData
                };
            }
            ControlFlowNode nodeTreatedAsExitNode           = null;
            bool            multipleNodesTreatedAsExitNodes = false;
            ControlFlowNode exitNode = new ControlFlowNode {
                UserIndex = -1
            };

            rev[cfg.Length] = exitNode;
            for (int i = 0; i < cfg.Length; i++)
            {
                if (!loopHead.Dominates(cfg[i]) || isSwitch && cfg[i] != loopHead && loopContext.MatchContinue(cfg[i]))
                {
                    continue;
                }

                // Add reverse edges for all edges in cfg
                foreach (var succ in cfg[i].Successors)
                {
                    // edges to outer loops still count as exits (labelled continue not implemented)
                    if (isSwitch && loopContext.MatchContinue(succ, 1))
                    {
                        continue;
                    }

                    if (loopHead.Dominates(succ))
                    {
                        rev[succ.UserIndex].AddEdgeTo(rev[i]);
                    }
                    else
                    {
                        if (nodeTreatedAsExitNode == null)
                        {
                            nodeTreatedAsExitNode = succ;
                        }
                        if (nodeTreatedAsExitNode != succ)
                        {
                            multipleNodesTreatedAsExitNodes = true;
                        }
                        exitNode.AddEdgeTo(rev[i]);
                    }
                }
                if (context.ControlFlowGraph.HasDirectExitOutOfContainer(cfg[i]))
                {
                    exitNode.AddEdgeTo(rev[i]);
                }
            }
            if (multipleNodesTreatedAsExitNodes)
            {
                exitNodeArity = 2;                 // more than 1
            }
            else if (nodeTreatedAsExitNode != null)
            {
                exitNodeArity = 1;
            }
            else
            {
                exitNodeArity = 0;
            }
            Dominance.ComputeDominance(exitNode, context.CancellationToken);
            return(rev);
        }