Ejemplo n.º 1
0
        public static List <BasicBlock> BuildBasicBlocks(List <IInstruction> ops)
        {
            // collect set of branch targets
            HashSet <IInstruction> BranchTargets = new HashSet <IInstruction>();

            foreach (IInstruction op in ops)
            {
                if (op is IJumpInstruction)
                {
                    IJumpInstruction it = op as IJumpInstruction;
                    BranchTargets.Add(it.Target);
                }
                else if (op is IBranchInstruction)
                {
                    IBranchInstruction it = op as IBranchInstruction;
                    BranchTargets.Add(it.IfTarget);
                    BranchTargets.Add(it.ElseTarget);
                }
            }

            // walk instruction list and split off blocks at branches or branch targets
            List <BasicBlock> Blocks = new List <BasicBlock>();
            int nInstructions        = ops.Count;
            int i = 0;

            do
            {
                BasicBlock block = new BasicBlock();
                Blocks.Add(block);

                do
                {
                    IInstruction op = ops[i++];
                    block.AddInstruction(op);
                    op.Block = block;

                    // stop if we just added a branch/jump op
                    if (op is IJumpInstruction || op is IBranchInstruction)
                    {
                        break;
                    }

                    // stop if next instruction is a branch target
                    if (i < nInstructions && BranchTargets.Contains(ops[i]))
                    {
                        break;
                    }
                } while (i < nInstructions);
            } while (i < nInstructions);

            // construct CFG edges
            for (int b = 0; b < Blocks.Count; b++)
            {
                IInstruction op = Blocks[b].LastInstruction;
                if (op is IBranchInstruction)
                {
                    IBranchInstruction branch = op as IBranchInstruction;
                    if (branch.IfTarget != null)
                    {
                        branch.Block.AddSuccessor(branch.IfTarget.Block);
                        branch.IfTarget.Block.AddPredecessor(branch.Block);
                    }
                    if (branch.ElseTarget != null)
                    {
                        branch.Block.AddSuccessor(branch.ElseTarget.Block);
                        branch.ElseTarget.Block.AddPredecessor(branch.Block);
                    }
                }
                else if (op is IJumpInstruction)
                {
                    // unconditional branch or jump, add target as one and only successor
                    IJumpInstruction jmp = op as IJumpInstruction;
                    if (jmp.Target != null)
                    {
                        jmp.Block.AddSuccessor(jmp.Target.Block);
                        jmp.Target.Block.AddPredecessor(jmp.Block);
                    }
                }
                else if (b < Blocks.Count - 1)
                {
                    // Block ends in something other than a branch or jump
                    //  add next block as successor
                    Blocks[b].AddSuccessor(Blocks[b + 1]);
                    Blocks[b + 1].AddPredecessor(Blocks[b]);
                }
            }

            return(Blocks);
        }
Ejemplo n.º 2
0
        public static List <IInstruction> DoTrace(List <IInstruction> ops, List <BasicBlock> blocks, List <Loop> loops, HashSet <IInstruction> takenBranches)
        {
            List <IInstruction>    Exec       = new List <IInstruction>();
            Dictionary <Loop, int> LoopCounts = new Dictionary <Loop, int>();

            foreach (Loop l in loops)
            {
                LoopCounts.Add(l, 0);
            }



            BasicBlock b = blocks.First();

            do
            {
                // execute all instructions in current block
                Exec.AddRange(b.Instructions);

                // if block ends in a branch, determine which edge to take
                IInstruction blockEnd = b.LastInstruction;
                BasicBlock   next     = null;
                if (blockEnd is IBranchInstruction)
                {
                    IBranchInstruction branch = blockEnd as IBranchInstruction;
                    if (branch.Category == BranchCategory.BREAK_BRANCH)
                    {
                        // take a break branch as soon as the iteration count reaches zero
                        BasicBlock exit   = branch.IfTarget.Block;
                        BasicBlock noexit = branch.ElseTarget.Block;
                        if (exit.InnerMostLoop == b.InnerMostLoop)
                        {
                            exit   = branch.ElseTarget.Block;
                            noexit = branch.IfTarget.Block;
                        }


                        if (LoopCounts[b.InnerMostLoop] >= b.InnerMostLoop.DesiredIterations)
                        {
                            LoopCounts[b.InnerMostLoop] = 0;
                            next = exit;
                        }
                        else
                        {
                            next = noexit;
                        }
                    }
                    else if (branch.Category == BranchCategory.LOOPSKIP_BRANCH)
                    {
                        // don't enter unless the loop's iteration count is non-zero
                        BasicBlock loop;
                        BasicBlock noloop;
                        if (branch.IfTarget.Block.InnerMostLoop != branch.Block.InnerMostLoop)
                        {
                            loop   = branch.IfTarget.Block;
                            noloop = branch.ElseTarget.Block;
                        }
                        else
                        {
                            loop   = branch.ElseTarget.Block;
                            noloop = branch.IfTarget.Block;
                        }

                        if (loop.InnerMostLoop.DesiredIterations > 0)
                        {
                            next = loop;
                        }
                        else
                        {
                            next = noloop;
                        }
                    }
                    else if (branch.Category == BranchCategory.CONTINUE_BRANCH)
                    {
                        // do NOT take a continue branch if the count's up
                        BasicBlock go   = branch.IfTarget.Block;
                        BasicBlock nogo = branch.ElseTarget.Block;
                        if (nogo == b.InnerMostLoop.Header)
                        {
                            go   = branch.ElseTarget.Block;
                            nogo = branch.IfTarget.Block; // swap if needed
                        }

                        if (LoopCounts[b.InnerMostLoop] >= b.InnerMostLoop.DesiredIterations)
                        {
                            next = nogo;
                        }
                        else
                        {
                            next = go;
                        }
                    }
                    else
                    {
                        if (takenBranches.Contains(branch))
                        {
                            next = branch.IfTarget.Block;
                        }
                        else
                        {
                            next = branch.ElseTarget.Block;
                        }
                    }
                }
                else if (blockEnd is IJumpInstruction)
                {
                    // if block ends in a jump, then jump
                    IJumpInstruction jump = blockEnd as IJumpInstruction;
                    next = jump.Target.Block;
                }
                else
                {
                    // otherwise, proceed to next successor block
                    if (b.SuccessorCount > 0)
                    {
                        next = b.Successors.First();
                    }
                }

                // increment loop count every time we pass a loop header
                if (b.InnerMostLoop != null && b.InnerMostLoop.Header == b)
                {
                    LoopCounts[b.InnerMostLoop]++;
                }

                b = next;
            } while (b != null);


            return(Exec);
        }