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); } } }
private GraphBlock CreateBlockAfter(GraphBlock before, string name) { var block = new GraphBlock(name); before.ConnectTo(block); return(block); }
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); }
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); }
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")); }
public GraphBlock BuildRaise(JToken node, GraphBlock current) { current.AddNode(node); foreach (var e in _exceptionHandlers.Last()) { current.ConnectTo(e); } current.Exited = true; return(current); }
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); } }
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); }
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); }
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); } } } }
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); }
public Graph(GraphBlock entry, GraphBlock exit) { Entry = entry; Exit = exit; }
private void Exit(GraphBlock current) { current.ConnectTo(_exit); current.Exited = true; }
private void EnterLoop(GraphBlock entry, GraphBlock exit) { _loopEntries.Add(entry); _loopExits.Add(exit); }
public GraphBlock BuildContinue(JToken node, GraphBlock current) { current.AddNode(node); Exit(_loopEntries.Last()); return(null); }
public GraphBlock BuildBreak(JToken node, GraphBlock current) { current.AddNode(node); Exit(_loopExits.Last()); return(null); }