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