Beispiel #1
0
        public void Dominates()
        {
            var cfg = new Graph();

            cfg.Nodes.Add("1");
            cfg.Nodes.Add("2");
            cfg.Nodes.Add("3");
            cfg.Nodes.Add("4");

            cfg.Edges.Add("1", "2");
            cfg.Edges.Add("2", "3");
            cfg.Edges.Add("3", "4");
            var info = new DominatorInfo(cfg.Nodes["1"]);

            Assert.True(info.Dominates(cfg.Nodes["1"], cfg.Nodes["1"]));
            Assert.True(info.Dominates(cfg.Nodes["1"], cfg.Nodes["2"]));
            Assert.True(info.Dominates(cfg.Nodes["1"], cfg.Nodes["3"]));
            Assert.True(info.Dominates(cfg.Nodes["1"], cfg.Nodes["4"]));

            Assert.False(info.Dominates(cfg.Nodes["2"], cfg.Nodes["1"]));
            Assert.True(info.Dominates(cfg.Nodes["2"], cfg.Nodes["2"]));
            Assert.True(info.Dominates(cfg.Nodes["2"], cfg.Nodes["3"]));
            Assert.True(info.Dominates(cfg.Nodes["2"], cfg.Nodes["4"]));

            Assert.False(info.Dominates(cfg.Nodes["3"], cfg.Nodes["1"]));
            Assert.False(info.Dominates(cfg.Nodes["3"], cfg.Nodes["2"]));
            Assert.True(info.Dominates(cfg.Nodes["3"], cfg.Nodes["3"]));
            Assert.True(info.Dominates(cfg.Nodes["3"], cfg.Nodes["4"]));

            Assert.False(info.Dominates(cfg.Nodes["4"], cfg.Nodes["1"]));
            Assert.False(info.Dominates(cfg.Nodes["4"], cfg.Nodes["2"]));
            Assert.False(info.Dominates(cfg.Nodes["4"], cfg.Nodes["3"]));
            Assert.True(info.Dominates(cfg.Nodes["4"], cfg.Nodes["4"]));
        }
Beispiel #2
0
        public void LoopFrontiers()
        {
            var info     = new DominatorInfo(LoopGraph.Nodes["1"]);
            var frontier = new HashSet <Node>(new[] { LoopGraph.Nodes["2"] });

            Assert.Equal(frontier, info.GetDominanceFrontier(LoopGraph.Nodes["2"]));
            Assert.Equal(frontier, info.GetDominanceFrontier(LoopGraph.Nodes["3"]));
        }
Beispiel #3
0
        public void LoopHeader()
        {
            var cfg  = LoopGraph;
            var info = new DominatorInfo(cfg.Nodes["1"]);

            Assert.True(info.IsLoopHeader(cfg.Nodes["2"]));
            Assert.False(info.IsLoopHeader(cfg.Nodes["1"]));
        }
Beispiel #4
0
        public void LoopDominators()
        {
            var info = new DominatorInfo(LoopGraph.Nodes["1"]);

            Assert.Equal(LoopGraph.Nodes["1"], info.GetImmediateDominator(LoopGraph.Nodes["1"]));
            Assert.Equal(LoopGraph.Nodes["1"], info.GetImmediateDominator(LoopGraph.Nodes["2"]));
            Assert.Equal(LoopGraph.Nodes["2"], info.GetImmediateDominator(LoopGraph.Nodes["3"]));
            Assert.Equal(LoopGraph.Nodes["2"], info.GetImmediateDominator(LoopGraph.Nodes["4"]));
        }
Beispiel #5
0
        public void IfStatementFrontiers()
        {
            var cfg      = IfStatementGraph;
            var info     = new DominatorInfo(IfStatementGraph.Nodes["1"]);
            var frontier = new HashSet <Node>(new[] { IfStatementGraph.Nodes["4"] });

            Assert.Equal(frontier, info.GetDominanceFrontier(IfStatementGraph.Nodes["3"]));
            Assert.Equal(frontier, info.GetDominanceFrontier(IfStatementGraph.Nodes["3"]));
        }
Beispiel #6
0
        public void LoopDominated()
        {
            var cfg  = LoopGraph;
            var info = new DominatorInfo(LoopGraph.Nodes["1"]);

            Assert.True(info.GetDominatedNodes(cfg.Nodes["1"]).SetEquals(cfg.Nodes));
            Assert.True(info.GetDominatedNodes(cfg.Nodes["2"]).SetEquals(new[] { cfg.Nodes["2"], cfg.Nodes["3"], cfg.Nodes["4"] }));
            Assert.True(info.GetDominatedNodes(cfg.Nodes["3"]).SetEquals(new[] { cfg.Nodes["3"] }));
            Assert.True(info.GetDominatedNodes(cfg.Nodes["4"]).SetEquals(new[] { cfg.Nodes["4"] }));
        }
Beispiel #7
0
        public void IfStatementDominated()
        {
            var cfg  = IfStatementGraph;
            var info = new DominatorInfo(IfStatementGraph.Nodes["1"]);

            Assert.True(info.GetDominatedNodes(cfg.Nodes["1"]).SetEquals(cfg.Nodes));
            Assert.True(info.GetDominatedNodes(cfg.Nodes["2"]).SetEquals(new[] { cfg.Nodes["2"] }));
            Assert.True(info.GetDominatedNodes(cfg.Nodes["3"]).SetEquals(new[] { cfg.Nodes["3"] }));
            Assert.True(info.GetDominatedNodes(cfg.Nodes["4"]).SetEquals(new[] { cfg.Nodes["4"] }));
        }
Beispiel #8
0
        public void IfStatementDominators()
        {
            var cfg = IfStatementGraph;

            var info = new DominatorInfo(cfg.Nodes["1"]);

            Assert.Equal(cfg.Nodes["1"], info.GetImmediateDominator(cfg.Nodes["1"]));
            Assert.Equal(cfg.Nodes["1"], info.GetImmediateDominator(cfg.Nodes["2"]));
            Assert.Equal(cfg.Nodes["1"], info.GetImmediateDominator(cfg.Nodes["3"]));
            Assert.Equal(cfg.Nodes["1"], info.GetImmediateDominator(cfg.Nodes["4"]));
        }
Beispiel #9
0
        public ILCompilationUnit(ControlFlowGraph controlFlowGraph, IFrameLayout frameLayout)
        {
            ControlFlowGraph = controlFlowGraph ?? throw new ArgumentNullException(nameof(controlFlowGraph));
            FrameLayout      = frameLayout;
            DominatorInfo    = new DominatorInfo(controlFlowGraph.Entrypoint);
            DominatorTree    = DominatorInfo.ToDominatorTree();

            for (int i = 0; i < frameLayout.Parameters.Count; i++)
            {
                var parameter = new ILParameter("arg_" + i, i);
                Parameters.Add(parameter);
                _variables.Add(parameter.Name, parameter);
            }
        }
Beispiel #10
0
        public BlockGenerator(ControlFlowGraph cfg, CilCodeGenerator generator)
        {
            _cfg       = cfg ?? throw new ArgumentNullException(nameof(cfg));
            _generator = generator;

            _dominatorInfo = new DominatorInfo(cfg.Entrypoint);
            _dominatorTree = _dominatorInfo.ToDominatorTree();

            var components = cfg.Entrypoint.FindStronglyConnectedComponents();

            _nodeToComponent = new Dictionary <Node, ISet <Node> >();
            foreach (var component in components)
            {
                foreach (var node in component)
                {
                    _nodeToComponent[node] = component;
                }
            }
        }
Beispiel #11
0
        private void AddAbnormalEdges(ControlFlowGraph graph)
        {
            if (graph.SubGraphs.Count == 0)
            {
                return;
            }

            // Since exception handlers make it possible to transfer control to the handler block
            // at any time, we have these "abnormal edges" from each node in the try block
            // to the first node in the handler block (or filter block).

            // First, add the initial abnormal handler edges from every try-start to the handler-start (or filter start).
            // This allows us to do some more dominator-magic, where we can just infer the handler body based
            // on the nodes dominated by the handler node.
            foreach (var subGraph in graph.SubGraphs.OrderBy(x => x.Nodes.Count))
            {
                var ehFrame = (EHFrame)subGraph.UserData[EHFrame.EHFrameProperty];

                // Find the try entry node.
                var tryEntry = GetNode(graph, (long)ehFrame.TryStart);
                tryEntry.UserData[ControlFlowGraph.TryStartProperty] = ehFrame;

                // Find the handler entry node.
                var handlerEntry = GetNode(graph, (long)ehFrame.HandlerAddress);
                handlerEntry.UserData[ControlFlowGraph.HandlerStartProperty] = ehFrame;

                // Add initial abnormal edge.
                if (ehFrame.Type != EHType.FILTER)
                {
                    // Jump straight to the handler entry.
                    AddAbnormalEdge(graph, tryEntry, ehFrame, handlerEntry);
                }
                else
                {
                    // Jump to the filter entry.
                    var filterEntry = GetNode(graph, (long)ehFrame.FilterAddress);
                    filterEntry.UserData[ControlFlowGraph.FilterStartProperty] = ehFrame;
                    AddAbnormalEdge(graph, tryEntry, ehFrame, filterEntry);

                    // Connect all terminators of the filter block to the handler entry.
                    foreach (var terminator in FindReachableReturnNodes(filterEntry))
                    {
                        AddAbnormalEdge(graph, terminator, ehFrame, handlerEntry);
                    }
                }
            }

            // Obtain dominator info.
            var dominatorInfo = new DominatorInfo(graph.Entrypoint);

            // Add all handler nodes to the cluster, and add abnormal edges for each try node to the handler start node.
            var handlerExits = new Dictionary <EHFrame, ICollection <Node> >();

            foreach (var subGraph in graph.SubGraphs.OrderBy(x => x.Nodes.Count))
            {
                var ehFrame      = (EHFrame)subGraph.UserData[EHFrame.EHFrameProperty];
                var tryEntry     = GetNode(graph, (long)ehFrame.TryStart);
                var handlerEntry = GetNode(graph, (long)ehFrame.HandlerAddress);

                // Determine the handler exits.
                var handlerBody = CollectHandlerNodes(handlerEntry, dominatorInfo.GetDominatedNodes(handlerEntry));
                foreach (var handlerNode in handlerBody)
                {
                    subGraph.Nodes.Add(handlerNode);
                }

                handlerExits.Add(ehFrame, new HashSet <Node>(handlerBody.Where(x => x.OutgoingEdges.Count == 0)));

                // Add for each node in the try block an abnormal edge.
                var tryBody = new HashSet <Node>(subGraph.Nodes.Except(handlerBody));
                foreach (var node in tryBody.Where(n =>
                                                   !n.UserData.ContainsKey(ControlFlowGraph.TopMostEHProperty) && n != tryEntry))
                {
                    AddAbnormalEdge(graph, node, ehFrame, handlerEntry);
                }

                // Register EH boundaries in the sub graph.
                subGraph.UserData[ControlFlowGraph.TryBlockProperty]     = tryBody;
                subGraph.UserData[ControlFlowGraph.HandlerBlockProperty] = handlerBody;

                if (ehFrame.Type == EHType.FILTER)
                {
                    var filterEntry = GetNode(graph, (long)ehFrame.FilterAddress);
                    subGraph.UserData[ControlFlowGraph.FilterStartProperty] = filterEntry;
                }
            }

            // Since a LEAVE instruction might not directly transfer control to the referenced instruction,
            // but rather transfer control to a finally block first,  we have to add edges to these nodes
            // as well.

            foreach (var node in graph.Nodes)
            {
                if (node.SubGraphs.Count > 0)
                {
                    // Check if the node ends with a LEAVE.
                    var block = GetUserData <ILBasicBlock>(node, ILBasicBlock.BasicBlockProperty);
                    if (block == null)
                    {
                        continue;
                    }

                    var last = block.Instructions[block.Instructions.Count - 1];
                    if (last.OpCode.Code == ILCode.LEAVE)
                    {
                        // Find the frame we're jumping out of.
                        var ehFrame = last.ProgramState.EHStack.Peek();

                        // Add for each handler exit an edge to the referenced instruction.
                        foreach (var exit in handlerExits[ehFrame])
                        {
                            var edge = CreateEdge(exit, node.OutgoingEdges.First().Target, ControlFlowGraph.EndFinallyConditionLabel);
                            exit.UserData[ControlFlowGraph.TopMostEHProperty] = ehFrame;
                            graph.Edges.Add(edge);
                        }
                    }
                }
            }
        }
Beispiel #12
0
        public void ComplexLoopTest()
        {
            var reader = new DotReader(new StringReader(@"
            strict digraph {
                1 -> 2 -> 3 -> 4 -> 3 -> 5 -> 6 -> 7
            }"));

            var cfg = reader.Read();

            var info = new DominatorInfo(cfg.Nodes["1"]);

            Assert.True(info.Dominates(cfg.Nodes["1"], cfg.Nodes["1"]));
            Assert.True(info.Dominates(cfg.Nodes["1"], cfg.Nodes["2"]));
            Assert.True(info.Dominates(cfg.Nodes["1"], cfg.Nodes["3"]));
            Assert.True(info.Dominates(cfg.Nodes["1"], cfg.Nodes["4"]));
            Assert.True(info.Dominates(cfg.Nodes["1"], cfg.Nodes["5"]));
            Assert.True(info.Dominates(cfg.Nodes["1"], cfg.Nodes["6"]));
            Assert.True(info.Dominates(cfg.Nodes["1"], cfg.Nodes["7"]));

            Assert.False(info.Dominates(cfg.Nodes["2"], cfg.Nodes["1"]));
            Assert.True(info.Dominates(cfg.Nodes["2"], cfg.Nodes["2"]));
            Assert.True(info.Dominates(cfg.Nodes["2"], cfg.Nodes["3"]));
            Assert.True(info.Dominates(cfg.Nodes["2"], cfg.Nodes["4"]));
            Assert.True(info.Dominates(cfg.Nodes["2"], cfg.Nodes["5"]));
            Assert.True(info.Dominates(cfg.Nodes["2"], cfg.Nodes["6"]));
            Assert.True(info.Dominates(cfg.Nodes["2"], cfg.Nodes["7"]));

            Assert.False(info.Dominates(cfg.Nodes["3"], cfg.Nodes["1"]));
            Assert.False(info.Dominates(cfg.Nodes["3"], cfg.Nodes["2"]));
            Assert.True(info.Dominates(cfg.Nodes["3"], cfg.Nodes["3"]));
            Assert.True(info.Dominates(cfg.Nodes["3"], cfg.Nodes["4"]));
            Assert.True(info.Dominates(cfg.Nodes["3"], cfg.Nodes["5"]));
            Assert.True(info.Dominates(cfg.Nodes["3"], cfg.Nodes["6"]));
            Assert.True(info.Dominates(cfg.Nodes["3"], cfg.Nodes["7"]));

            Assert.False(info.Dominates(cfg.Nodes["4"], cfg.Nodes["1"]));
            Assert.False(info.Dominates(cfg.Nodes["4"], cfg.Nodes["2"]));
            Assert.False(info.Dominates(cfg.Nodes["4"], cfg.Nodes["3"]));
            Assert.True(info.Dominates(cfg.Nodes["4"], cfg.Nodes["4"]));
            Assert.False(info.Dominates(cfg.Nodes["4"], cfg.Nodes["5"]));
            Assert.False(info.Dominates(cfg.Nodes["4"], cfg.Nodes["6"]));
            Assert.False(info.Dominates(cfg.Nodes["4"], cfg.Nodes["7"]));

            Assert.False(info.Dominates(cfg.Nodes["5"], cfg.Nodes["1"]));
            Assert.False(info.Dominates(cfg.Nodes["5"], cfg.Nodes["2"]));
            Assert.False(info.Dominates(cfg.Nodes["5"], cfg.Nodes["3"]));
            Assert.False(info.Dominates(cfg.Nodes["5"], cfg.Nodes["4"]));
            Assert.True(info.Dominates(cfg.Nodes["5"], cfg.Nodes["5"]));
            Assert.True(info.Dominates(cfg.Nodes["5"], cfg.Nodes["6"]));
            Assert.True(info.Dominates(cfg.Nodes["5"], cfg.Nodes["7"]));

            Assert.False(info.Dominates(cfg.Nodes["6"], cfg.Nodes["1"]));
            Assert.False(info.Dominates(cfg.Nodes["6"], cfg.Nodes["2"]));
            Assert.False(info.Dominates(cfg.Nodes["6"], cfg.Nodes["3"]));
            Assert.False(info.Dominates(cfg.Nodes["6"], cfg.Nodes["4"]));
            Assert.False(info.Dominates(cfg.Nodes["6"], cfg.Nodes["5"]));
            Assert.True(info.Dominates(cfg.Nodes["6"], cfg.Nodes["6"]));
            Assert.True(info.Dominates(cfg.Nodes["6"], cfg.Nodes["7"]));

            Assert.False(info.Dominates(cfg.Nodes["7"], cfg.Nodes["1"]));
            Assert.False(info.Dominates(cfg.Nodes["7"], cfg.Nodes["2"]));
            Assert.False(info.Dominates(cfg.Nodes["7"], cfg.Nodes["3"]));
            Assert.False(info.Dominates(cfg.Nodes["7"], cfg.Nodes["4"]));
            Assert.False(info.Dominates(cfg.Nodes["7"], cfg.Nodes["5"]));
            Assert.False(info.Dominates(cfg.Nodes["7"], cfg.Nodes["6"]));
            Assert.True(info.Dominates(cfg.Nodes["7"], cfg.Nodes["7"]));
        }