예제 #1
0
        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));
        }
예제 #2
0
		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();
		}
예제 #3
0
		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());

			}
		}
예제 #4
0
		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);
		}
예제 #5
0
        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());
        }
예제 #6
0
        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());
            }
        }