示例#1
0
        public IEnumerable <GraphBlock> ReverseVisitBlocks(GraphBlock start = null)
        {
            if (start == null)
            {
                start = Exit;
            }

            var visited = new HashSet <GraphBlock>();
            var stack   = new Stack <GraphBlock>();

            stack.Push(start);

            while (stack.Count > 0)
            {
                var b = stack.Pop();
                if (visited.Contains(b))
                {
                    continue;
                }

                yield return(b);

                visited.Add(b);
                foreach (var o in b.InBlocks)
                {
                    stack.Push(o);
                }
            }
        }
示例#2
0
        private GraphBlock CreateBlockAfter(GraphBlock before, string name)
        {
            var block = new GraphBlock(name);

            before.ConnectTo(block);
            return(block);
        }
示例#3
0
        public Graph Build(JToken node)
        {
            _entry             = new GraphBlock("entry");
            _exit              = new GraphBlock("exit");
            _loopEntries       = new List <GraphBlock>();
            _loopExits         = new List <GraphBlock>();
            _exceptionHandlers = new List <List <GraphBlock> >();
            _exceptionHandlers.Add(new List <GraphBlock>(new[] { _exit }));

            var last = Build(node, _entry);

            last.ConnectTo(_exit);

            var graph = new Graph(_entry, _exit);

            File.WriteAllText(@"..\..\graph0.dot", graph.GetDotString());

            graph.CombineEmptyBlocks();

            File.WriteAllText(@"..\..\graph.dot", graph.GetDotString());

            graph.FillDominators();
            graph.FillIDoms();

            graph.FillDominantChildren();
            graph.FillDominanceFrontiers();

            File.WriteAllText(@"..\..\graph.txt", graph.GetGraphString());

            return(graph);
        }
示例#4
0
        public GraphBlock BuildIf(JToken node, GraphBlock current)
        {
            var id = current.Id;

            current.AddNode(node);

            var body = CreateBlockAfter(current, $"{id}:if_body");

            body = Build(node["body"], body);

            if (node["orelse"].Count() == 0)
            {
                var array = (JArray)node["orelse"];
                array.Add(JToken.Parse("{ \"_Name\": \"Pass\" }"));
            }

            var orelse = CreateBlockAfter(current, $"{id}:if_orelse");

            orelse = Build(node["orelse"], orelse);

            var exit = new GraphBlock($"{id}:if_exit");

            body.ConnectTo(exit);
            orelse.ConnectTo(exit);

            return(exit);
        }
示例#5
0
        public GraphBlock BuildCall(JToken node, GraphBlock current)
        {
            current.AddNode(node);

            foreach (var e in _exceptionHandlers.Last())
            {
                current.ConnectTo(e);
            }

            return(CreateBlockAfter(current, "next_to_call"));
        }
示例#6
0
        public GraphBlock BuildRaise(JToken node, GraphBlock current)
        {
            current.AddNode(node);
            foreach (var e in _exceptionHandlers.Last())
            {
                current.ConnectTo(e);
            }

            current.Exited = true;

            return(current);
        }
示例#7
0
        private void GetGraphString(GraphBlock block, int indent, StringBuilder result, HashSet <GraphBlock> visited)
        {
            if (visited.Contains(block))
            {
                return;
            }
            visited.Add(block);

            result.Append(new string(' ', indent * 2));
            result.AppendLine(block.ToString());

            foreach (var b in block.OutBlocks)
            {
                GetGraphString(b, indent + 1, result, visited);
            }
        }
示例#8
0
        private GraphBlock Build(JToken nodes, GraphBlock current)
        {
            foreach (var n in nodes)
            {
                if (n.Type != JTokenType.Object)
                {
                    throw new ArgumentException("Attempt to add non-object node");
                }

                var name = ObjectNameOf(n);
                switch (name)
                {
                case "For": current = BuildFor(n, current); break;

                case "While": current = BuildWhile(n, current); break;

                case "If": current = BuildIf(n, current); break;

                case "Raise": current = BuildRaise(n, current); break;

                case "Try": current = BuildTry(n, current); break;

                case "Break": current = BuildBreak(n, current); break;

                case "Continue": current = BuildContinue(n, current); break;

                case "Call": current = BuildCall(n, current); break;

                default:
                    current.AddNode(n);
                    break;
                }

                if (current.Exited)
                {
                    break;
                }
            }

            return(current);
        }
示例#9
0
        public GraphBlock BuildWhile(JToken node, GraphBlock current)
        {
            var id = current.Id;

            var entry = CreateBlockAfter(current, $"{id}:while_entry");

            entry.AddNode(node);
            _loopEntries.Add(entry);

            var body = CreateBlockAfter(entry, $"{id}:while_body");
            var exit = new GraphBlock($"{id}:while_exit");

            EnterLoop(entry, exit);
            body = Build(node["body"], body);
            ExitLoop();

            body.ConnectTo(entry);
            body.ConnectTo(exit);

            return(exit);
        }
示例#10
0
        public void FillDominanceFrontiers(GraphBlock block)
        {
            foreach (var b in block.OutBlocks)
            {
                if (b.IDom != block)
                {
                    block.DominanceFrontiers.Add(b);
                }
            }

            foreach (var b in block.DominantChildren)
            {
                FillDominanceFrontiers(b);
                foreach (var df in b.DominanceFrontiers)
                {
                    if (!df.Dominators.Contains(block))
                    {
                        block.DominanceFrontiers.Add(df);
                    }
                }
            }
        }
示例#11
0
        public GraphBlock BuildTry(JToken node, GraphBlock current)
        {
            var id = current.Id;

            var exit     = new GraphBlock($"{id}:try_exit");
            var handlers = new List <GraphBlock>();

            foreach (var handler in node["handlers"])
            {
                var h = Build(handler["body"], new GraphBlock($"{id}:eh"));
                h.ConnectTo(exit);

                handlers.Add(h);
            }

            if (handlers.Count > 0)
            {
                _exceptionHandlers.Add(handlers);
            }

            if (node["finalbody"].Count() > 0)
            {
                throw new NotImplementedException("finally");
            }

            EnterTry(handlers);
            var body = Build(node["body"], current);

            ExitTry();

            if (!body.Exited)
            {
                body.ConnectTo(exit);
                return(exit);
            }

            return(null);
        }
示例#12
0
 public Graph(GraphBlock entry, GraphBlock exit)
 {
     Entry = entry;
     Exit  = exit;
 }
示例#13
0
 private void Exit(GraphBlock current)
 {
     current.ConnectTo(_exit);
     current.Exited = true;
 }
示例#14
0
 private void EnterLoop(GraphBlock entry, GraphBlock exit)
 {
     _loopEntries.Add(entry);
     _loopExits.Add(exit);
 }
示例#15
0
 public GraphBlock BuildContinue(JToken node, GraphBlock current)
 {
     current.AddNode(node);
     Exit(_loopEntries.Last());
     return(null);
 }
示例#16
0
 public GraphBlock BuildBreak(JToken node, GraphBlock current)
 {
     current.AddNode(node);
     Exit(_loopExits.Last());
     return(null);
 }