private static BasicBlock HandleStatement( BasicBlock start, BasicBlock enclosing_loop_frontier, IList <BasicBlock> bblist, Dictionary <BasicBlock, IEnumerable <BasicBlock> > pred, Dictionary <BasicBlock, List <BasicBlock> > dom, GraphPathFinder path_finder, List <TreeStatement> code) { BasicBlock loop_tail; try { loop_tail = pred[start].Where(bb => dom[bb].Contains(start)).SingleOrDefault(); } catch (InvalidOperationException e) { throw new IrreducibleCFGException("Loop must have only one route to its header from its body"); } if (loop_tail != null) { IEnumerable <BasicBlock> loop_insiders = bblist.Where( bb => path_finder.GetPathLength(bb, loop_tail) < (int)short.MaxValue && !path_finder.GetPath(bb, loop_tail).Contains(start) && dom[bb].Contains(start)).Add(start); BasicBlock loop_frontier; try { loop_frontier = (from insider in loop_insiders from adj in new [] { insider.Target, insider.Successor } where adj != null && !loop_insiders.Contains(adj) select adj).Single(); } catch (InvalidOperationException e) { throw new IrreducibleCFGException("Loop must have only one exit route from its body"); } List <TreeStatement> loop_body = start.Code.Select(bbi => new InstructionStatement(bbi) as TreeStatement).ToList(); BasicBlock statement_cursor = HandleBranch(start.Trailer, loop_frontier, bblist, pred, dom, path_finder, loop_body); while (statement_cursor != start) { statement_cursor = HandleStatement(statement_cursor, loop_frontier, bblist, pred, dom, path_finder, loop_body); } code.Add(new InfiniteLoopStatement(loop_body)); return(loop_frontier); } code.AddRange(start.Code.Select(bbi => new InstructionStatement(bbi))); return(HandleBranch(start.Trailer, enclosing_loop_frontier, bblist, pred, dom, path_finder, code)); }
public static IList<TreeStatement> BuildAST(this Subprogram src) { IList<BasicBlock> bblist = src.GetBasicBlocks(); Dictionary<BasicBlock, IEnumerable<BasicBlock>> pred = bblist.Select(bb => new KeyValuePair<BasicBlock, IEnumerable<BasicBlock>>(bb, bblist.Where(bbel => bbel.Successor == bb || bbel.Target == bb))). ToDictionary(kvp => kvp.Key, kvp => kvp.Value); // Determine dominators. Dictionary<BasicBlock, List<BasicBlock>> dom = bblist.Select(bb => new KeyValuePair<BasicBlock, List<BasicBlock>>(bb, bb == src.CFGRoot ? new List<BasicBlock> { src.CFGRoot } : bblist.ToList())). ToDictionary(kvp => kvp.Key, kvp => kvp.Value); bool changes = true; while (changes) { changes = false; foreach (BasicBlock n in bblist) { if (n != src.CFGRoot) { IEnumerable<BasicBlock> doms = null; foreach (BasicBlock p in pred[n]) doms = (doms == null) ? dom[p] : doms.Intersect(dom[p]); doms = doms.Union(new [] { n }); if (!doms.SequenceEqual(dom[n])) { changes = true; dom[n] = new List<BasicBlock>(doms); } } } } // Perform depth-first enumeration. Dictionary<BasicBlock, int> dfn = bblist.Select(bb => new KeyValuePair<BasicBlock, int>(bb, 0)). ToDictionary(kvp => kvp.Key, kvp => kvp.Value); int c = bblist.Count; NumDepth(src.CFGRoot, dfn, ref c, new List<BasicBlock>()); // Test CFG reducibility: each retreating edge must be back edge. foreach (BasicBlock sbb in bblist) { foreach (BasicBlock tbb in new [] { sbb.Successor, sbb.Target }) { if (tbb != null && dfn[tbb] < dfn[sbb] && !dom[sbb].Contains(tbb)) throw new IrreducibleCFGException("There is non-back retreating edge"); } } if (bblist.Where(bb => bb.Trailer.OpCode == IROpCodes.RET).Count() != 1) throw new IrreducibleCFGException("Control flow graph must have single node with RET ending"); List<TreeStatement> code = new List<TreeStatement>(); BasicBlock cur = src.CFGRoot; GraphPathFinder path_finder = new GraphPathFinder(bblist); while (cur != null) cur = HandleStatement(cur, null, bblist, pred, dom, path_finder, code); return code.AsReadOnly(); }
private static BasicBlock HandleBranch( ControlFlowInstruction cfi, BasicBlock enclosing_loop_frontier, IList<BasicBlock> bblist, Dictionary<BasicBlock, IEnumerable<BasicBlock>> pred, Dictionary<BasicBlock, List<BasicBlock>> dom, GraphPathFinder path_finder, List<TreeStatement> code) { JumpInstruction jump = cfi as JumpInstruction; JumpIfInstruction jumpif = cfi as JumpIfInstruction; switch (cfi.OpCode) { case IROpCodes.RET: return null; case IROpCodes.JMP: return jump.Target; case IROpCodes.JT: case IROpCodes.JF: { // loop condition check if (jumpif.Target == enclosing_loop_frontier) { // while-do break condition check code.Add(new BranchStatement( jumpif.Flag, cfi.OpCode == IROpCodes.JT ? new TreeStatement[] { new BreakStatement() } : null, cfi.OpCode == IROpCodes.JF ? new TreeStatement[] { new BreakStatement() } : null)); return jumpif.Next; } if (jumpif.Next == enclosing_loop_frontier) { // do-while continue condition check code.Add(new BranchStatement( jumpif.Flag, cfi.OpCode == IROpCodes.JF ? new TreeStatement[] { new BreakStatement() } : null, cfi.OpCode == IROpCodes.JT ? new TreeStatement[] { new BreakStatement() } : null)); return jumpif.Target; } // initialize IF statement frontier with enclosing loop frontier or the last block in CFG BasicBlock frontier = (enclosing_loop_frontier != null) ? enclosing_loop_frontier : bblist.Single(bb => bb.Trailer.OpCode == IROpCodes.RET); // precise IF statement frontier with last common block in reversed paths going // from initial frontier value to both successors of basic block ending with this branch IEnumerator<BasicBlock> targetPathRev = path_finder.GetPath(jumpif.Target, frontier).Reverse().GetEnumerator(); IEnumerator<BasicBlock> nextPathRev = path_finder.GetPath(jumpif.Next, frontier).Reverse().GetEnumerator(); while (targetPathRev.MoveNext() && nextPathRev.MoveNext() && targetPathRev.Current == nextPathRev.Current) frontier = targetPathRev.Current; List<TreeStatement> trueBranchCode = new List<TreeStatement>(); List<TreeStatement> falseBranchCode = new List<TreeStatement>(); BasicBlock cursor; cursor = cfi.OpCode == IROpCodes.JT ? jumpif.Target : jumpif.Next; while (cursor != frontier) cursor = HandleStatement(cursor, null, bblist, pred, dom, path_finder, trueBranchCode); cursor = cfi.OpCode == IROpCodes.JF ? jumpif.Target : jumpif.Next; while (cursor != frontier) cursor = HandleStatement(cursor, null, bblist, pred, dom, path_finder, falseBranchCode); code.Add(new BranchStatement(jumpif.Flag, trueBranchCode, falseBranchCode)); return frontier; } default: throw new NotSupportedException(cfi.OpCode.ToString()); } }
private static BasicBlock HandleStatement( BasicBlock start, BasicBlock enclosing_loop_frontier, IList<BasicBlock> bblist, Dictionary<BasicBlock, IEnumerable<BasicBlock>> pred, Dictionary<BasicBlock, List<BasicBlock>> dom, GraphPathFinder path_finder, List<TreeStatement> code) { BasicBlock loop_tail; try { loop_tail = pred[start].Where(bb => dom[bb].Contains(start)).SingleOrDefault(); } catch (InvalidOperationException e) { throw new IrreducibleCFGException("Loop must have only one route to its header from its body"); } if (loop_tail != null) { IEnumerable<BasicBlock> loop_insiders = bblist.Where( bb => path_finder.GetPathLength(bb, loop_tail) < (int)short.MaxValue && !path_finder.GetPath(bb, loop_tail).Contains(start) && dom[bb].Contains(start)).Add(start); BasicBlock loop_frontier; try { loop_frontier = (from insider in loop_insiders from adj in new [] { insider.Target, insider.Successor } where adj != null && !loop_insiders.Contains(adj) select adj).Single(); } catch (InvalidOperationException e) { throw new IrreducibleCFGException("Loop must have only one exit route from its body"); } List<TreeStatement> loop_body = start.Code.Select(bbi => new InstructionStatement(bbi) as TreeStatement).ToList(); BasicBlock statement_cursor = HandleBranch(start.Trailer, loop_frontier, bblist, pred, dom, path_finder, loop_body); while (statement_cursor != start) statement_cursor = HandleStatement(statement_cursor, loop_frontier, bblist, pred, dom, path_finder, loop_body); code.Add(new InfiniteLoopStatement(loop_body)); return loop_frontier; } code.AddRange(start.Code.Select(bbi => new InstructionStatement(bbi))); return HandleBranch(start.Trailer, enclosing_loop_frontier, bblist, pred, dom, path_finder, code); }
public static IList <TreeStatement> BuildAST(this Subprogram src) { IList <BasicBlock> bblist = src.GetBasicBlocks(); Dictionary <BasicBlock, IEnumerable <BasicBlock> > pred = bblist.Select(bb => new KeyValuePair <BasicBlock, IEnumerable <BasicBlock> >(bb, bblist.Where(bbel => bbel.Successor == bb || bbel.Target == bb))). ToDictionary(kvp => kvp.Key, kvp => kvp.Value); // Determine dominators. Dictionary <BasicBlock, List <BasicBlock> > dom = bblist.Select(bb => new KeyValuePair <BasicBlock, List <BasicBlock> >(bb, bb == src.CFGRoot ? new List <BasicBlock> { src.CFGRoot } : bblist.ToList())). ToDictionary(kvp => kvp.Key, kvp => kvp.Value); bool changes = true; while (changes) { changes = false; foreach (BasicBlock n in bblist) { if (n != src.CFGRoot) { IEnumerable <BasicBlock> doms = null; foreach (BasicBlock p in pred[n]) { doms = (doms == null) ? dom[p] : doms.Intersect(dom[p]); } doms = doms.Union(new [] { n }); if (!doms.SequenceEqual(dom[n])) { changes = true; dom[n] = new List <BasicBlock>(doms); } } } } // Perform depth-first enumeration. Dictionary <BasicBlock, int> dfn = bblist.Select(bb => new KeyValuePair <BasicBlock, int>(bb, 0)). ToDictionary(kvp => kvp.Key, kvp => kvp.Value); int c = bblist.Count; NumDepth(src.CFGRoot, dfn, ref c, new List <BasicBlock>()); // Test CFG reducibility: each retreating edge must be back edge. foreach (BasicBlock sbb in bblist) { foreach (BasicBlock tbb in new [] { sbb.Successor, sbb.Target }) { if (tbb != null && dfn[tbb] < dfn[sbb] && !dom[sbb].Contains(tbb)) { throw new IrreducibleCFGException("There is non-back retreating edge"); } } } if (bblist.Where(bb => bb.Trailer.OpCode == IROpCodes.RET).Count() != 1) { throw new IrreducibleCFGException("Control flow graph must have single node with RET ending"); } List <TreeStatement> code = new List <TreeStatement>(); BasicBlock cur = src.CFGRoot; GraphPathFinder path_finder = new GraphPathFinder(bblist); while (cur != null) { cur = HandleStatement(cur, null, bblist, pred, dom, path_finder, code); } return(code.AsReadOnly()); }
private static BasicBlock HandleBranch( ControlFlowInstruction cfi, BasicBlock enclosing_loop_frontier, IList <BasicBlock> bblist, Dictionary <BasicBlock, IEnumerable <BasicBlock> > pred, Dictionary <BasicBlock, List <BasicBlock> > dom, GraphPathFinder path_finder, List <TreeStatement> code) { JumpInstruction jump = cfi as JumpInstruction; JumpIfInstruction jumpif = cfi as JumpIfInstruction; switch (cfi.OpCode) { case IROpCodes.RET: return(null); case IROpCodes.JMP: return(jump.Target); case IROpCodes.JT: case IROpCodes.JF: { // loop condition check if (jumpif.Target == enclosing_loop_frontier) { // while-do break condition check code.Add(new BranchStatement( jumpif.Flag, cfi.OpCode == IROpCodes.JT ? new TreeStatement[] { new BreakStatement() } : null, cfi.OpCode == IROpCodes.JF ? new TreeStatement[] { new BreakStatement() } : null)); return(jumpif.Next); } if (jumpif.Next == enclosing_loop_frontier) { // do-while continue condition check code.Add(new BranchStatement( jumpif.Flag, cfi.OpCode == IROpCodes.JF ? new TreeStatement[] { new BreakStatement() } : null, cfi.OpCode == IROpCodes.JT ? new TreeStatement[] { new BreakStatement() } : null)); return(jumpif.Target); } // initialize IF statement frontier with enclosing loop frontier or the last block in CFG BasicBlock frontier = (enclosing_loop_frontier != null) ? enclosing_loop_frontier : bblist.Single(bb => bb.Trailer.OpCode == IROpCodes.RET); // precise IF statement frontier with last common block in reversed paths going // from initial frontier value to both successors of basic block ending with this branch IEnumerator <BasicBlock> targetPathRev = path_finder.GetPath(jumpif.Target, frontier).Reverse().GetEnumerator(); IEnumerator <BasicBlock> nextPathRev = path_finder.GetPath(jumpif.Next, frontier).Reverse().GetEnumerator(); while (targetPathRev.MoveNext() && nextPathRev.MoveNext() && targetPathRev.Current == nextPathRev.Current) { frontier = targetPathRev.Current; } List <TreeStatement> trueBranchCode = new List <TreeStatement>(); List <TreeStatement> falseBranchCode = new List <TreeStatement>(); BasicBlock cursor; cursor = cfi.OpCode == IROpCodes.JT ? jumpif.Target : jumpif.Next; while (cursor != frontier) { cursor = HandleStatement(cursor, null, bblist, pred, dom, path_finder, trueBranchCode); } cursor = cfi.OpCode == IROpCodes.JF ? jumpif.Target : jumpif.Next; while (cursor != frontier) { cursor = HandleStatement(cursor, null, bblist, pred, dom, path_finder, falseBranchCode); } code.Add(new BranchStatement(jumpif.Flag, trueBranchCode, falseBranchCode)); return(frontier); } default: throw new NotSupportedException(cfi.OpCode.ToString()); } }