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)); }
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); }
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()); } }